├── .github └── workflows │ └── maven-install.yml ├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src ├── main ├── 358 │ └── org.apache.paimon.trino │ │ ├── DecimalUtils.java │ │ ├── TrinoConnectorFactory.java │ │ ├── TrinoHandleResolver.java │ │ ├── TrinoMetadata.java │ │ ├── TrinoPageSource.java │ │ ├── TrinoSplitManager.java │ │ └── TrinoSplitSource.java ├── 385 │ └── org.apache.paimon.trino │ │ ├── DecimalUtils.java │ │ ├── TrinoConnectorFactory.java │ │ ├── TrinoMetadata.java │ │ ├── TrinoPageSource.java │ │ ├── TrinoSplitManager.java │ │ └── TrinoSplitSource.java ├── 388 │ └── org │ │ └── apache │ │ └── paimon │ │ └── trino │ │ ├── DecimalUtils.java │ │ ├── TrinoConnectorFactory.java │ │ ├── TrinoMetadata.java │ │ ├── TrinoPageSource.java │ │ ├── TrinoSplitManager.java │ │ └── TrinoSplitSource.java ├── java │ └── org │ │ └── apache │ │ └── paimon │ │ └── trino │ │ ├── ClassLoaderUtils.java │ │ ├── EncodingUtils.java │ │ ├── FieldNameUtils.java │ │ ├── TrinoColumnHandle.java │ │ ├── TrinoConnector.java │ │ ├── TrinoConnectorFactoryBase.java │ │ ├── TrinoFilterConverter.java │ │ ├── TrinoMetadataBase.java │ │ ├── TrinoPageSourceBase.java │ │ ├── TrinoPageSourceProvider.java │ │ ├── TrinoPlugin.java │ │ ├── TrinoSplit.java │ │ ├── TrinoSplitManagerBase.java │ │ ├── TrinoSplitSourceBase.java │ │ ├── TrinoTableHandle.java │ │ ├── TrinoTransactionHandle.java │ │ └── TrinoTypeUtils.java └── resources │ └── META-INF │ └── services │ └── io.trino.spi.Plugin └── test ├── java └── org │ └── apache │ └── paimon │ └── trino │ ├── SimpleTableTestHelper.java │ └── TestTrinoITCase.java └── resources └── log4j2-test.properties /.github/workflows/maven-install.yml: -------------------------------------------------------------------------------- 1 | name: maven install 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout code 11 | uses: actions/checkout@v2 12 | - name: Set up JDK 11 13 | uses: actions/setup-java@v1 14 | with: 15 | java-version: 11 16 | - name: Build 17 | run: | 18 | mvn clean install 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | .classpath 3 | .idea 4 | .metadata 5 | .settings 6 | .project 7 | target 8 | .version.properties 9 | *.class 10 | *.iml 11 | *.swp 12 | *.jar 13 | *.zip 14 | *.log 15 | *.pyc 16 | .DS_Store 17 | *.ipr 18 | *.iws 19 | dependency-reduced-pom.xml 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This has been migrated to https://github.com/apache/incubator-paimon-trino 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 23 | 4.0.0 24 | 25 | 26 | org.apache 27 | apache 28 | 23 29 | 30 | 31 | org.apache.paimon 32 | paimon-trino 33 | Paimon : Trino 34 | 0.4-SNAPSHOT 35 | 36 | jar 37 | 38 | 39 | 388 40 | 388 41 | 11 42 | 2.8.5 43 | 1.7.32 44 | 2.17.1 45 | 46 | 47 | 48 | 49 | org.apache.paimon 50 | paimon-bundle 51 | ${project.version} 52 | 53 | 54 | 55 | io.trino 56 | trino-plugin-toolkit 57 | ${trino.version} 58 | provided 59 | 60 | 61 | 62 | io.trino 63 | trino-spi 64 | ${trino.version} 65 | provided 66 | 67 | 68 | 69 | io.airlift 70 | configuration 71 | 216 72 | 73 | 74 | 75 | io.airlift 76 | slice 77 | 0.42 78 | provided 79 | 80 | 81 | 82 | org.apache.commons 83 | commons-lang3 84 | 3.3.2 85 | 86 | 87 | 88 | org.slf4j 89 | slf4j-api 90 | ${slf4j.version} 91 | 92 | 93 | 94 | org.apache.logging.log4j 95 | log4j-api 96 | ${log4j.version} 97 | 98 | 99 | 100 | org.apache.logging.log4j 101 | log4j-core 102 | ${log4j.version} 103 | 104 | 105 | 106 | 107 | org.apache.logging.log4j 108 | log4j-1.2-api 109 | ${log4j.version} 110 | 111 | 112 | 113 | com.google.guava 114 | guava 115 | 31.1-jre 116 | 117 | 118 | 119 | 120 | io.trino 121 | trino-client 122 | ${trino.version} 123 | test 124 | 125 | 126 | 127 | io.trino 128 | trino-main 129 | ${trino.version} 130 | test 131 | 132 | 133 | log4j 134 | log4j 135 | 136 | 137 | org.slf4j 138 | slf4j-log4j12 139 | 140 | 141 | 142 | 143 | 144 | io.trino 145 | trino-testing 146 | ${trino.version} 147 | test 148 | 149 | 150 | 151 | org.apache.hadoop 152 | hadoop-common 153 | ${hadoop.version} 154 | test 155 | 156 | 157 | log4j 158 | log4j 159 | 160 | 161 | org.slf4j 162 | slf4j-log4j12 163 | 164 | 165 | 166 | 167 | 168 | org.apache.hadoop 169 | hadoop-client 170 | ${hadoop.version} 171 | test 172 | 173 | 174 | log4j 175 | log4j 176 | 177 | 178 | org.slf4j 179 | slf4j-log4j12 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | trino-358 189 | 190 | 358 191 | 358 192 | 11 193 | 194 | 195 | 196 | trino-385 197 | 198 | 385 199 | 385 200 | 11 201 | 202 | 203 | 204 | trino-391 205 | 206 | 391 207 | 388 208 | 17 209 | 210 | 211 | 212 | trino-409 213 | 214 | 409 215 | 388 216 | 17 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | org.apache.maven.plugins 225 | maven-shade-plugin 226 | 227 | 228 | shade-flink 229 | package 230 | 231 | shade 232 | 233 | 234 | 235 | 236 | org.apache.paimon:paimon-bundle 237 | org.slf4j:slf4j-api 238 | org.xerial.snappy:snappy-java 239 | org.apache.commons:commons-lang3 240 | org.apache.logging.log4j:log4j-api 241 | org.apache.logging.log4j:log4j-core 242 | org.apache.logging.log4j:log4j-slf4j-impl 243 | org.apache.logging.log4j:log4j-1.2-api 244 | com.google.guava:guava 245 | 246 | 247 | 248 | 249 | 251 | 252 | 254 | Apache Paimon 255 | UTF-8 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | org.codehaus.mojo 265 | build-helper-maven-plugin 266 | 267 | 268 | add-sources 269 | generate-sources 270 | 271 | add-source 272 | 273 | 274 | 275 | src/main/${trino.shade.version} 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | org.apache.maven.plugins 287 | maven-compiler-plugin 288 | 3.8.0 289 | 290 | ${target.java.version} 291 | ${target.java.version} 292 | 293 | false 294 | 295 | 296 | -Xpkginfo:always 297 | 298 | 299 | 300 | 301 | 302 | org.apache.maven.plugins 303 | maven-enforcer-plugin 304 | 3.0.0-M1 305 | 306 | 307 | 308 | 309 | org.apache.maven.plugins 310 | maven-shade-plugin 311 | 3.1.1 312 | 313 | 314 | 315 | 316 | org.apache.maven.plugins 317 | maven-site-plugin 318 | 319 | 320 | attach-descriptor 321 | none 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /src/main/358/org.apache.paimon.trino/DecimalUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.airlift.slice.Slice; 22 | import java.math.BigInteger; 23 | import io.trino.spi.type.Decimals; 24 | 25 | public class DecimalUtils { 26 | 27 | public static BigInteger toBigInteger(Object value) { 28 | return Decimals.decodeUnscaledValue((Slice) value); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/358/org.apache.paimon.trino/TrinoConnectorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorFactory; 22 | import io.trino.spi.connector.ConnectorHandleResolver; 23 | 24 | /** Trino {@link ConnectorFactory}. */ 25 | public class TrinoConnectorFactory extends TrinoConnectorFactoryBase { 26 | 27 | @Override 28 | public ConnectorHandleResolver getHandleResolver() { 29 | return new TrinoHandleResolver(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/358/org.apache.paimon.trino/TrinoHandleResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ColumnHandle; 22 | import io.trino.spi.connector.ConnectorHandleResolver; 23 | import io.trino.spi.connector.ConnectorSplit; 24 | import io.trino.spi.connector.ConnectorTableHandle; 25 | import io.trino.spi.connector.ConnectorTransactionHandle; 26 | 27 | public class TrinoHandleResolver 28 | implements ConnectorHandleResolver 29 | { 30 | @Override 31 | public Class getTransactionHandleClass() 32 | { 33 | return TrinoTransactionHandle.class; 34 | } 35 | 36 | @Override 37 | public Class getTableHandleClass() 38 | { 39 | return TrinoTableHandle.class; 40 | } 41 | 42 | @Override 43 | public Class getColumnHandleClass() 44 | { 45 | return TrinoColumnHandle.class; 46 | } 47 | 48 | @Override 49 | public Class getSplitClass() 50 | { 51 | return TrinoSplit.class; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/358/org.apache.paimon.trino/TrinoMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.options.Options; 22 | 23 | public class TrinoMetadata extends TrinoMetadataBase { 24 | 25 | public TrinoMetadata(Options catalogOptions) { 26 | super(catalogOptions); 27 | } 28 | 29 | @Override 30 | public boolean usesLegacyTableLayouts() { 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/358/org.apache.paimon.trino/TrinoPageSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ColumnHandle; 22 | 23 | import org.apache.paimon.data.InternalRow; 24 | import org.apache.paimon.reader.RecordReader; 25 | 26 | import java.util.List; 27 | 28 | public class TrinoPageSource extends TrinoPageSourceBase { 29 | 30 | public TrinoPageSource(RecordReader reader, List projectedColumns) { 31 | super(reader, projectedColumns); 32 | } 33 | 34 | @Override 35 | public long getSystemMemoryUsage() { 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/358/org.apache.paimon.trino/TrinoSplitManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorSession; 22 | import io.trino.spi.connector.ConnectorSplitSource; 23 | import io.trino.spi.connector.ConnectorTableHandle; 24 | import io.trino.spi.connector.ConnectorTransactionHandle; 25 | import io.trino.spi.connector.DynamicFilter; 26 | 27 | public class TrinoSplitManager extends TrinoSplitManagerBase { 28 | 29 | @Override 30 | public ConnectorSplitSource getSplits( 31 | ConnectorTransactionHandle transaction, 32 | ConnectorSession session, 33 | ConnectorTableHandle table, 34 | SplitSchedulingStrategy splitSchedulingStrategy, 35 | DynamicFilter dynamicFilter) { 36 | return getSplits(table, session); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/358/org.apache.paimon.trino/TrinoSplitSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorPartitionHandle; 22 | 23 | import java.util.List; 24 | import java.util.concurrent.CompletableFuture; 25 | 26 | public class TrinoSplitSource extends TrinoSplitSourceBase { 27 | 28 | public TrinoSplitSource(List splits) { 29 | super(splits); 30 | } 31 | 32 | @Override 33 | public CompletableFuture getNextBatch( 34 | ConnectorPartitionHandle partitionHandle, int maxSize) { 35 | return innerGetNextBatch(maxSize); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/385/org.apache.paimon.trino/DecimalUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.type.Int128; 22 | import java.math.BigInteger; 23 | 24 | public class DecimalUtils { 25 | 26 | public static BigInteger toBigInteger(Object value) { 27 | return ((Int128) value).toBigInteger(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/385/org.apache.paimon.trino/TrinoConnectorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | public class TrinoConnectorFactory extends TrinoConnectorFactoryBase { 22 | } 23 | -------------------------------------------------------------------------------- /src/main/385/org.apache.paimon.trino/TrinoMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.options.Options; 22 | 23 | public class TrinoMetadata extends TrinoMetadataBase { 24 | 25 | public TrinoMetadata(Options catalogOptions) { 26 | super(catalogOptions); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/385/org.apache.paimon.trino/TrinoPageSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ColumnHandle; 22 | 23 | import org.apache.paimon.data.InternalRow; 24 | import org.apache.paimon.reader.RecordReader; 25 | 26 | import java.util.List; 27 | 28 | public class TrinoPageSource extends TrinoPageSourceBase { 29 | 30 | public TrinoPageSource(RecordReader reader, List projectedColumns) { 31 | super(reader, projectedColumns); 32 | } 33 | 34 | @Override 35 | public long getMemoryUsage() { 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/385/org.apache.paimon.trino/TrinoSplitManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorSession; 22 | import io.trino.spi.connector.ConnectorSplitManager; 23 | import io.trino.spi.connector.ConnectorSplitSource; 24 | import io.trino.spi.connector.ConnectorTableHandle; 25 | import io.trino.spi.connector.ConnectorTransactionHandle; 26 | import io.trino.spi.connector.Constraint; 27 | import io.trino.spi.connector.DynamicFilter; 28 | 29 | public class TrinoSplitManager extends TrinoSplitManagerBase { 30 | 31 | @Override 32 | public ConnectorSplitSource getSplits( 33 | ConnectorTransactionHandle transaction, 34 | ConnectorSession session, 35 | ConnectorTableHandle table, 36 | ConnectorSplitManager.SplitSchedulingStrategy splitSchedulingStrategy, 37 | DynamicFilter dynamicFilter, 38 | Constraint constraint) { 39 | return getSplits(table, session); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/385/org.apache.paimon.trino/TrinoSplitSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorPartitionHandle; 22 | 23 | 24 | import java.util.List; 25 | import java.util.concurrent.CompletableFuture; 26 | 27 | public class TrinoSplitSource extends TrinoSplitSourceBase { 28 | 29 | public TrinoSplitSource(List splits) { 30 | super(splits); 31 | } 32 | 33 | @Override 34 | public CompletableFuture getNextBatch(ConnectorPartitionHandle partitionHandle, int maxSize) { 35 | return innerGetNextBatch(maxSize); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/388/org/apache/paimon/trino/DecimalUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.type.Int128; 22 | import java.math.BigInteger; 23 | 24 | public class DecimalUtils { 25 | 26 | public static BigInteger toBigInteger(Object value) { 27 | return ((Int128) value).toBigInteger(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/388/org/apache/paimon/trino/TrinoConnectorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | public class TrinoConnectorFactory extends TrinoConnectorFactoryBase { 22 | } 23 | -------------------------------------------------------------------------------- /src/main/388/org/apache/paimon/trino/TrinoMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.options.Options; 22 | 23 | public class TrinoMetadata extends TrinoMetadataBase { 24 | 25 | public TrinoMetadata(Options catalogOptions) { 26 | super(catalogOptions); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/388/org/apache/paimon/trino/TrinoPageSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ColumnHandle; 22 | 23 | import org.apache.paimon.data.InternalRow; 24 | import org.apache.paimon.reader.RecordReader; 25 | 26 | import java.util.List; 27 | 28 | public class TrinoPageSource extends TrinoPageSourceBase { 29 | 30 | public TrinoPageSource(RecordReader reader, List projectedColumns) { 31 | super(reader, projectedColumns); 32 | } 33 | 34 | @Override 35 | public long getMemoryUsage() { 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/388/org/apache/paimon/trino/TrinoSplitManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorSession; 22 | import io.trino.spi.connector.ConnectorSplitSource; 23 | import io.trino.spi.connector.ConnectorTableHandle; 24 | import io.trino.spi.connector.ConnectorTransactionHandle; 25 | import io.trino.spi.connector.Constraint; 26 | import io.trino.spi.connector.DynamicFilter; 27 | 28 | public class TrinoSplitManager extends TrinoSplitManagerBase { 29 | 30 | @Override 31 | public ConnectorSplitSource getSplits( 32 | ConnectorTransactionHandle transaction, 33 | ConnectorSession session, 34 | ConnectorTableHandle table, 35 | DynamicFilter dynamicFilter, 36 | Constraint constraint) { 37 | return getSplits(table, session); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/388/org/apache/paimon/trino/TrinoSplitSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import java.util.List; 22 | import java.util.concurrent.CompletableFuture; 23 | 24 | public class TrinoSplitSource extends TrinoSplitSourceBase { 25 | 26 | public TrinoSplitSource(List splits) { 27 | super(splits); 28 | } 29 | 30 | @Override 31 | public CompletableFuture getNextBatch(int maxSize) { 32 | return innerGetNextBatch(maxSize); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/ClassLoaderUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import java.util.function.Supplier; 22 | 23 | /** Utils for {@link ClassLoader}. */ 24 | public class ClassLoaderUtils { 25 | 26 | public static T runWithContextClassLoader(Supplier supplier, ClassLoader classLoader) { 27 | ClassLoader previous = Thread.currentThread().getContextClassLoader(); 28 | Thread.currentThread().setContextClassLoader(classLoader); 29 | try { 30 | return supplier.get(); 31 | } finally { 32 | Thread.currentThread().setContextClassLoader(previous); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/EncodingUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.utils.InstantiationUtil; 22 | 23 | 24 | import java.util.Base64; 25 | 26 | import static java.nio.charset.StandardCharsets.UTF_8; 27 | 28 | /** Utils for encoding. */ 29 | public class EncodingUtils { 30 | 31 | private static final Base64.Encoder BASE64_ENCODER = 32 | java.util.Base64.getUrlEncoder().withoutPadding(); 33 | 34 | private static final Base64.Decoder BASE64_DECODER = java.util.Base64.getUrlDecoder(); 35 | 36 | public static String encodeObjectToString(T t) { 37 | try { 38 | byte[] bytes = InstantiationUtil.serializeObject(t); 39 | return new String(BASE64_ENCODER.encode(bytes), UTF_8); 40 | } catch (Exception e) { 41 | throw new RuntimeException(e); 42 | } 43 | } 44 | 45 | public static T decodeStringToObject(String encodedStr) { 46 | final byte[] bytes = BASE64_DECODER.decode(encodedStr.getBytes(UTF_8)); 47 | try { 48 | return InstantiationUtil.deserializeObject(bytes, EncodingUtils.class.getClassLoader()); 49 | } catch (Exception e) { 50 | throw new RuntimeException(e); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/FieldNameUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.types.DataField; 22 | import org.apache.paimon.types.RowType; 23 | 24 | 25 | import java.util.List; 26 | import java.util.stream.Collectors; 27 | 28 | public class FieldNameUtils { 29 | 30 | public static List fieldNames(RowType rowType) { 31 | return rowType.getFields().stream() 32 | .map(DataField::name) 33 | .map(String::toLowerCase) 34 | .collect(Collectors.toList()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoColumnHandle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import com.fasterxml.jackson.annotation.JsonCreator; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import io.trino.spi.connector.ColumnHandle; 24 | import io.trino.spi.connector.ColumnMetadata; 25 | import io.trino.spi.type.Type; 26 | 27 | import org.apache.paimon.utils.JsonSerdeUtil; 28 | import org.apache.paimon.types.DataType; 29 | import org.apache.paimon.types.DataTypeJsonParser; 30 | 31 | 32 | import static java.util.Objects.requireNonNull; 33 | 34 | /** Trino {@link ColumnHandle}. */ 35 | public final class TrinoColumnHandle implements ColumnHandle { 36 | private final String columnName; 37 | private final String typeString; 38 | private final Type trinoType; 39 | 40 | @JsonCreator 41 | public TrinoColumnHandle( 42 | @JsonProperty("columnName") String columnName, 43 | @JsonProperty("typeString") String typeString, 44 | @JsonProperty("trinoType") Type trinoType) { 45 | this.columnName = requireNonNull(columnName, "columnName is null"); 46 | this.typeString = requireNonNull(typeString, "columnType is null"); 47 | this.trinoType = requireNonNull(trinoType, "columnType is null"); 48 | } 49 | 50 | public static TrinoColumnHandle of(String columnName, DataType columnType) { 51 | return new TrinoColumnHandle( 52 | columnName, 53 | JsonSerdeUtil.toJson(columnType), 54 | TrinoTypeUtils.fromFlinkType(columnType)); 55 | } 56 | 57 | @JsonProperty 58 | public String getColumnName() { 59 | return columnName; 60 | } 61 | 62 | @JsonProperty 63 | public String getTypeString() { 64 | return typeString; 65 | } 66 | 67 | @JsonProperty 68 | public Type getTrinoType() { 69 | return trinoType; 70 | } 71 | 72 | public DataType logicalType() { 73 | return JsonSerdeUtil.fromJson(typeString, DataType.class); 74 | } 75 | 76 | public ColumnMetadata getColumnMetadata() { 77 | return new ColumnMetadata(columnName, trinoType); 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | return columnName.hashCode(); 83 | } 84 | 85 | @Override 86 | public boolean equals(Object obj) { 87 | if (this == obj) { 88 | return true; 89 | } 90 | if ((obj == null) || (getClass() != obj.getClass())) { 91 | return false; 92 | } 93 | 94 | TrinoColumnHandle other = (TrinoColumnHandle) obj; 95 | return columnName.equals(other.columnName); 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | return "{" 101 | + "columnName='" 102 | + columnName 103 | + '\'' 104 | + ", typeString='" 105 | + typeString 106 | + '\'' 107 | + ", trinoType=" 108 | + trinoType 109 | + '}'; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoConnector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.Connector; 22 | import io.trino.spi.connector.ConnectorTransactionHandle; 23 | import io.trino.spi.session.PropertyMetadata; 24 | import io.trino.spi.transaction.IsolationLevel; 25 | import org.apache.paimon.CoreOptions; 26 | 27 | 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | import static io.trino.spi.transaction.IsolationLevel.READ_COMMITTED; 32 | import static io.trino.spi.transaction.IsolationLevel.checkConnectorSupports; 33 | import static java.util.Objects.requireNonNull; 34 | import static org.apache.paimon.CoreOptions.SCAN_SNAPSHOT_ID; 35 | import static org.apache.paimon.CoreOptions.SCAN_TIMESTAMP_MILLIS; 36 | import static org.apache.paimon.trino.TrinoTableHandle.SCAN_TIMESTAMP; 37 | import static org.apache.paimon.trino.TrinoTableHandle.SCAN_SNAPSHOT; 38 | 39 | /** Trino {@link Connector}. */ 40 | public class TrinoConnector implements Connector { 41 | private final TrinoMetadataBase trinoMetadata; 42 | private final TrinoSplitManagerBase trinoSplitManager; 43 | private final TrinoPageSourceProvider trinoPageSourceProvider; 44 | 45 | public TrinoConnector( 46 | TrinoMetadataBase trinoMetadata, 47 | TrinoSplitManagerBase trinoSplitManager, 48 | TrinoPageSourceProvider trinoPageSourceProvider) { 49 | this.trinoMetadata = requireNonNull(trinoMetadata, "jmxMetadata is null"); 50 | this.trinoSplitManager = requireNonNull(trinoSplitManager, "jmxSplitManager is null"); 51 | this.trinoPageSourceProvider = 52 | requireNonNull(trinoPageSourceProvider, "jmxRecordSetProvider is null"); 53 | } 54 | 55 | @Override 56 | public ConnectorTransactionHandle beginTransaction( 57 | IsolationLevel isolationLevel, boolean readOnly) { 58 | checkConnectorSupports(READ_COMMITTED, isolationLevel); 59 | return TrinoTransactionHandle.INSTANCE; 60 | } 61 | 62 | @Override 63 | public TrinoMetadataBase getMetadata(ConnectorTransactionHandle transactionHandle) { 64 | return trinoMetadata; 65 | } 66 | 67 | @Override 68 | public TrinoSplitManagerBase getSplitManager() { 69 | return trinoSplitManager; 70 | } 71 | 72 | @Override 73 | public TrinoPageSourceProvider getPageSourceProvider() { 74 | return trinoPageSourceProvider; 75 | } 76 | 77 | @Override 78 | public List> getSessionProperties() { 79 | return Arrays.asList( 80 | PropertyMetadata.longProperty( 81 | SCAN_TIMESTAMP, 82 | SCAN_TIMESTAMP_MILLIS.description().toString(), 83 | null, 84 | true), 85 | PropertyMetadata.longProperty( 86 | SCAN_SNAPSHOT, 87 | SCAN_SNAPSHOT_ID.description().toString(), 88 | null, 89 | true) 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoConnectorFactoryBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.options.Options; 22 | 23 | import java.util.Map; 24 | 25 | import io.trino.spi.connector.Connector; 26 | import io.trino.spi.connector.ConnectorContext; 27 | import io.trino.spi.connector.ConnectorFactory; 28 | 29 | /** Trino {@link ConnectorFactory}. */ 30 | public abstract class TrinoConnectorFactoryBase implements ConnectorFactory { 31 | @Override 32 | public String getName() { 33 | return "paimon"; 34 | } 35 | 36 | @Override 37 | public Connector create( 38 | String catalogName, Map config, ConnectorContext context) { 39 | return new TrinoConnector( 40 | new TrinoMetadata(Options.fromMap(config)), 41 | new TrinoSplitManager(), 42 | new TrinoPageSourceProvider()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoFilterConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.data.BinaryString; 22 | import org.apache.paimon.data.Decimal; 23 | import org.apache.paimon.data.Timestamp; 24 | import org.apache.paimon.predicate.Predicate; 25 | import org.apache.paimon.predicate.PredicateBuilder; 26 | import org.apache.paimon.types.RowType; 27 | 28 | import io.airlift.slice.Slice; 29 | import io.trino.spi.predicate.Domain; 30 | import io.trino.spi.predicate.Range; 31 | import io.trino.spi.predicate.TupleDomain; 32 | import io.trino.spi.type.ArrayType; 33 | import io.trino.spi.type.BigintType; 34 | import io.trino.spi.type.BooleanType; 35 | import io.trino.spi.type.DateType; 36 | import io.trino.spi.type.DecimalType; 37 | import io.trino.spi.type.DoubleType; 38 | import io.trino.spi.type.IntegerType; 39 | import io.trino.spi.type.LongTimestampWithTimeZone; 40 | import io.trino.spi.type.MapType; 41 | import io.trino.spi.type.RealType; 42 | import io.trino.spi.type.Type; 43 | import io.trino.spi.type.VarbinaryType; 44 | import io.trino.spi.type.VarcharType; 45 | 46 | import java.math.BigDecimal; 47 | import java.util.ArrayList; 48 | import java.util.List; 49 | import java.util.Map; 50 | import java.util.Optional; 51 | 52 | import static io.trino.spi.type.TimeType.TIME_MILLIS; 53 | import static io.trino.spi.type.TimestampType.TIMESTAMP_MILLIS; 54 | import static io.trino.spi.type.TimestampWithTimeZoneType.TIMESTAMP_TZ_MILLIS; 55 | import static io.trino.spi.type.Timestamps.PICOSECONDS_PER_MILLISECOND; 56 | import static java.lang.Float.intBitsToFloat; 57 | import static java.lang.Math.toIntExact; 58 | import static java.util.Objects.requireNonNull; 59 | import static org.apache.paimon.predicate.PredicateBuilder.and; 60 | import static org.apache.paimon.predicate.PredicateBuilder.or; 61 | 62 | /** Trino filter to flink predicate. */ 63 | public class TrinoFilterConverter { 64 | 65 | private final RowType rowType; 66 | private final PredicateBuilder builder; 67 | 68 | public TrinoFilterConverter(RowType rowType) { 69 | this.rowType = rowType; 70 | this.builder = new PredicateBuilder(rowType); 71 | } 72 | 73 | public Optional convert(TupleDomain tupleDomain) { 74 | if (tupleDomain.isAll()) { 75 | // TODO alwaysTrue 76 | return Optional.empty(); 77 | } 78 | 79 | if (tupleDomain.getDomains().isEmpty()) { 80 | // TODO alwaysFalse 81 | return Optional.empty(); 82 | } 83 | 84 | Map domainMap = tupleDomain.getDomains().get(); 85 | List conjuncts = new ArrayList<>(); 86 | List fieldNames = FieldNameUtils.fieldNames(rowType); 87 | for (Map.Entry entry : domainMap.entrySet()) { 88 | TrinoColumnHandle columnHandle = entry.getKey(); 89 | Domain domain = entry.getValue(); 90 | int index = fieldNames.indexOf(columnHandle.getColumnName()); 91 | if (index != -1) { 92 | try { 93 | conjuncts.add(toPredicate(index, columnHandle.getTrinoType(), domain)); 94 | } catch (UnsupportedOperationException ignored) { 95 | } 96 | } 97 | } 98 | 99 | if (conjuncts.isEmpty()) { 100 | return Optional.empty(); 101 | } 102 | return Optional.of(and(conjuncts)); 103 | } 104 | 105 | private Predicate toPredicate(int columnIndex, Type type, Domain domain) { 106 | if (domain.isAll()) { 107 | // TODO alwaysTrue 108 | throw new UnsupportedOperationException(); 109 | } 110 | if (domain.getValues().isNone()) { 111 | if (domain.isNullAllowed()) { 112 | return builder.isNull((columnIndex)); 113 | } 114 | // TODO alwaysFalse 115 | throw new UnsupportedOperationException(); 116 | } 117 | 118 | if (domain.getValues().isAll()) { 119 | if (domain.isNullAllowed()) { 120 | // TODO alwaysTrue 121 | throw new UnsupportedOperationException(); 122 | } 123 | return builder.isNotNull((columnIndex)); 124 | } 125 | 126 | // TODO support structural types 127 | if (type instanceof ArrayType 128 | || type instanceof MapType 129 | || type instanceof io.trino.spi.type.RowType) { 130 | // Fail fast. Ignoring expression could lead to data loss in case of deletions. 131 | throw new UnsupportedOperationException(); 132 | } 133 | 134 | if (type.isOrderable()) { 135 | List orderedRanges = domain.getValues().getRanges().getOrderedRanges(); 136 | List values = new ArrayList<>(); 137 | List predicates = new ArrayList<>(); 138 | for (Range range : orderedRanges) { 139 | if (range.isSingleValue()) { 140 | values.add(getLiteralValue(type, range.getLowBoundedValue())); 141 | } else { 142 | predicates.add(toPredicate(columnIndex, range)); 143 | } 144 | } 145 | 146 | if (!values.isEmpty()) { 147 | predicates.add(builder.in(columnIndex, values)); 148 | } 149 | 150 | if (domain.isNullAllowed()) { 151 | predicates.add(builder.isNull(columnIndex)); 152 | } 153 | return or(predicates); 154 | } 155 | 156 | throw new UnsupportedOperationException(); 157 | } 158 | 159 | private Predicate toPredicate(int columnIndex, Range range) { 160 | Type type = range.getType(); 161 | 162 | if (range.isSingleValue()) { 163 | Object value = getLiteralValue(type, range.getSingleValue()); 164 | return builder.equal(columnIndex, value); 165 | } 166 | 167 | List conjuncts = new ArrayList<>(2); 168 | if (!range.isLowUnbounded()) { 169 | Object low = getLiteralValue(type, range.getLowBoundedValue()); 170 | Predicate lowBound; 171 | if (range.isLowInclusive()) { 172 | lowBound = builder.greaterOrEqual(columnIndex, low); 173 | } else { 174 | lowBound = builder.greaterThan(columnIndex, low); 175 | } 176 | conjuncts.add(lowBound); 177 | } 178 | 179 | if (!range.isHighUnbounded()) { 180 | Object high = getLiteralValue(type, range.getHighBoundedValue()); 181 | Predicate highBound; 182 | if (range.isHighInclusive()) { 183 | highBound = builder.lessOrEqual(columnIndex, high); 184 | } else { 185 | highBound = builder.lessThan(columnIndex, high); 186 | } 187 | conjuncts.add(highBound); 188 | } 189 | 190 | return and(conjuncts); 191 | } 192 | 193 | private Object getLiteralValue(Type type, Object trinoNativeValue) { 194 | requireNonNull(trinoNativeValue, "trinoNativeValue is null"); 195 | 196 | if (type instanceof BooleanType) { 197 | return trinoNativeValue; 198 | } 199 | 200 | if (type instanceof IntegerType) { 201 | return toIntExact((long) trinoNativeValue); 202 | } 203 | 204 | if (type instanceof BigintType) { 205 | return trinoNativeValue; 206 | } 207 | 208 | if (type instanceof RealType) { 209 | return intBitsToFloat(toIntExact((long) trinoNativeValue)); 210 | } 211 | 212 | if (type instanceof DoubleType) { 213 | return trinoNativeValue; 214 | } 215 | 216 | if (type instanceof DateType) { 217 | return toIntExact(((Long) trinoNativeValue)); 218 | } 219 | 220 | if (type.equals(TIME_MILLIS)) { 221 | return (int) ((long) trinoNativeValue / PICOSECONDS_PER_MILLISECOND); 222 | } 223 | 224 | if (type.equals(TIMESTAMP_MILLIS)) { 225 | return Timestamp.fromEpochMillis((long) trinoNativeValue / 1000); 226 | } 227 | 228 | if (type.equals(TIMESTAMP_TZ_MILLIS)) { 229 | return Timestamp.fromEpochMillis( 230 | ((LongTimestampWithTimeZone) trinoNativeValue).getEpochMillis()); 231 | } 232 | 233 | if (type instanceof VarcharType) { 234 | return BinaryString.fromBytes(((Slice) trinoNativeValue).getBytes()); 235 | } 236 | 237 | if (type instanceof VarbinaryType) { 238 | return ((Slice) trinoNativeValue).getBytes(); 239 | } 240 | 241 | if (type instanceof DecimalType) { 242 | DecimalType decimalType = (DecimalType) type; 243 | BigDecimal bigDecimal; 244 | if (trinoNativeValue instanceof Long) { 245 | bigDecimal = 246 | BigDecimal.valueOf((long) trinoNativeValue) 247 | .movePointLeft(decimalType.getScale()); 248 | } else { 249 | bigDecimal = 250 | new BigDecimal( 251 | DecimalUtils.toBigInteger(trinoNativeValue), decimalType.getScale()); 252 | } 253 | return Decimal.fromBigDecimal( 254 | bigDecimal, decimalType.getPrecision(), decimalType.getScale()); 255 | } 256 | 257 | throw new UnsupportedOperationException("Unsupported type: " + type); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoMetadataBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.catalog.CatalogContext; 22 | import org.apache.paimon.catalog.Catalog; 23 | import org.apache.paimon.catalog.CatalogFactory; 24 | import org.apache.paimon.catalog.Identifier; 25 | import org.apache.paimon.options.CatalogOptions; 26 | import org.apache.paimon.options.Options; 27 | import org.apache.paimon.utils.InstantiationUtil; 28 | 29 | import io.trino.spi.connector.Assignment; 30 | import io.trino.spi.connector.ColumnHandle; 31 | import io.trino.spi.connector.ColumnMetadata; 32 | import io.trino.spi.connector.ConnectorMetadata; 33 | import io.trino.spi.connector.ConnectorSession; 34 | import io.trino.spi.connector.ConnectorTableHandle; 35 | import io.trino.spi.connector.ConnectorTableMetadata; 36 | import io.trino.spi.connector.ConnectorTableProperties; 37 | import io.trino.spi.connector.Constraint; 38 | import io.trino.spi.connector.ConstraintApplicationResult; 39 | import io.trino.spi.connector.ProjectionApplicationResult; 40 | import io.trino.spi.connector.SchemaTableName; 41 | import io.trino.spi.connector.SchemaTablePrefix; 42 | import io.trino.spi.expression.ConnectorExpression; 43 | import io.trino.spi.predicate.TupleDomain; 44 | 45 | 46 | import java.io.IOException; 47 | import java.io.UncheckedIOException; 48 | import java.util.ArrayList; 49 | import java.util.Collections; 50 | import java.util.HashMap; 51 | import java.util.HashSet; 52 | import java.util.List; 53 | import java.util.Map; 54 | import java.util.Optional; 55 | import java.util.function.Function; 56 | 57 | import static java.util.Objects.requireNonNull; 58 | import static java.util.stream.Collectors.toList; 59 | import static java.util.stream.Collectors.toMap; 60 | 61 | /** Trino {@link ConnectorMetadata}. */ 62 | public abstract class TrinoMetadataBase implements ConnectorMetadata { 63 | 64 | private final Catalog catalog; 65 | 66 | public TrinoMetadataBase(Options catalogOptions) { 67 | this.catalog = CatalogFactory.createCatalog(CatalogContext.create(catalogOptions)); 68 | } 69 | 70 | @Override 71 | public List listSchemaNames(ConnectorSession session) { 72 | return listSchemaNames(); 73 | } 74 | 75 | private List listSchemaNames() { 76 | return catalog.listDatabases(); 77 | } 78 | 79 | @Override 80 | public TrinoTableHandle getTableHandle(ConnectorSession session, SchemaTableName tableName) { 81 | return getTableHandle(tableName); 82 | } 83 | 84 | @Override 85 | public ConnectorTableProperties getTableProperties( 86 | ConnectorSession session, ConnectorTableHandle table) { 87 | return new ConnectorTableProperties(); 88 | } 89 | 90 | public TrinoTableHandle getTableHandle(SchemaTableName tableName) { 91 | Identifier tablePath = new Identifier(tableName.getSchemaName(), tableName.getTableName()); 92 | byte[] serializedTable; 93 | try { 94 | serializedTable = InstantiationUtil.serializeObject(catalog.getTable(tablePath)); 95 | } catch (Catalog.TableNotExistException e) { 96 | return null; 97 | } catch (IOException e) { 98 | throw new UncheckedIOException(e); 99 | } 100 | 101 | return new TrinoTableHandle( 102 | tableName.getSchemaName(), 103 | tableName.getTableName(), 104 | serializedTable); 105 | } 106 | 107 | @Override 108 | public ConnectorTableMetadata getTableMetadata( 109 | ConnectorSession session, ConnectorTableHandle tableHandle) { 110 | return ((TrinoTableHandle) tableHandle).tableMetadata(); 111 | } 112 | 113 | @Override 114 | public List listTables(ConnectorSession session, Optional schemaName) { 115 | List tables = new ArrayList<>(); 116 | schemaName 117 | .map(Collections::singletonList) 118 | .orElseGet(catalog::listDatabases) 119 | .forEach(schema -> tables.addAll(listTables(schema))); 120 | return tables; 121 | } 122 | 123 | private List listTables(String schema) { 124 | try { 125 | return catalog.listTables(schema).stream() 126 | .map(table -> new SchemaTableName(schema, table)) 127 | .collect(toList()); 128 | } catch (Catalog.DatabaseNotExistException e) { 129 | throw new RuntimeException(e); 130 | } 131 | } 132 | 133 | @Override 134 | public Map getColumnHandles( 135 | ConnectorSession session, ConnectorTableHandle tableHandle) { 136 | TrinoTableHandle table = (TrinoTableHandle) tableHandle; 137 | Map handleMap = new HashMap<>(); 138 | for (ColumnMetadata column : table.columnMetadatas()) { 139 | handleMap.put(column.getName(), table.columnHandle(column.getName())); 140 | } 141 | return handleMap; 142 | } 143 | 144 | @Override 145 | public ColumnMetadata getColumnMetadata( 146 | ConnectorSession session, ConnectorTableHandle tableHandle, ColumnHandle columnHandle) { 147 | return ((TrinoColumnHandle) columnHandle).getColumnMetadata(); 148 | } 149 | 150 | @Override 151 | public Map> listTableColumns(ConnectorSession session, SchemaTablePrefix prefix) { 152 | requireNonNull(prefix, "prefix is null"); 153 | List tableNames; 154 | if (prefix.getTable().isPresent()) { 155 | tableNames = Collections.singletonList(prefix.toSchemaTableName()); 156 | } else { 157 | tableNames = listTables(session, prefix.getSchema()); 158 | } 159 | 160 | return tableNames.stream().collect(toMap( 161 | Function.identity(), 162 | table -> getTableHandle(session, table).columnMetadatas())); 163 | } 164 | 165 | @Override 166 | public Optional> applyFilter( 167 | ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { 168 | TrinoTableHandle trinoTableHandle = (TrinoTableHandle) handle; 169 | TupleDomain oldFilter = trinoTableHandle.getFilter(); 170 | TupleDomain newFilter = 171 | constraint 172 | .getSummary() 173 | .transformKeys(TrinoColumnHandle.class::cast) 174 | .intersect(oldFilter); 175 | if (oldFilter.equals(newFilter)) { 176 | return Optional.empty(); 177 | } 178 | 179 | return Optional.of( 180 | new ConstraintApplicationResult<>( 181 | trinoTableHandle.copy(newFilter), constraint.getSummary(), false)); 182 | } 183 | 184 | @Override 185 | public Optional> applyProjection( 186 | ConnectorSession session, 187 | ConnectorTableHandle handle, 188 | List projections, 189 | Map assignments) { 190 | TrinoTableHandle trinoTableHandle = (TrinoTableHandle) handle; 191 | List newColumns = new ArrayList<>(assignments.values()); 192 | 193 | if (trinoTableHandle.getProjectedColumns().isPresent() 194 | && containSameElements(newColumns, trinoTableHandle.getProjectedColumns().get())) { 195 | return Optional.empty(); 196 | } 197 | 198 | List assignmentList = new ArrayList<>(); 199 | assignments.forEach( 200 | (name, column) -> 201 | assignmentList.add( 202 | new Assignment( 203 | name, 204 | column, 205 | ((TrinoColumnHandle) column).getTrinoType()))); 206 | 207 | return Optional.of( 208 | new ProjectionApplicationResult<>( 209 | trinoTableHandle.copy(Optional.of(newColumns)), projections, assignmentList, false)); 210 | } 211 | 212 | private static boolean containSameElements( 213 | List first, List second) { 214 | return new HashSet<>(first).equals(new HashSet<>(second)); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoPageSourceBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.data.BinaryString; 22 | import org.apache.paimon.data.Decimal; 23 | import org.apache.paimon.data.InternalArray; 24 | import org.apache.paimon.data.InternalMap; 25 | import org.apache.paimon.data.InternalRow; 26 | import org.apache.paimon.data.Timestamp; 27 | import org.apache.paimon.reader.RecordReader; 28 | import org.apache.paimon.reader.RecordReader.RecordIterator; 29 | import org.apache.paimon.types.DataType; 30 | import org.apache.paimon.types.DataTypeChecks; 31 | import org.apache.paimon.utils.InternalRowUtils; 32 | 33 | import io.airlift.slice.Slice; 34 | import io.trino.spi.Page; 35 | import io.trino.spi.PageBuilder; 36 | import io.trino.spi.TrinoException; 37 | import io.trino.spi.block.Block; 38 | import io.trino.spi.block.BlockBuilder; 39 | import io.trino.spi.connector.ColumnHandle; 40 | import io.trino.spi.connector.ConnectorPageSource; 41 | import io.trino.spi.type.ArrayType; 42 | import io.trino.spi.type.DecimalType; 43 | import io.trino.spi.type.Decimals; 44 | import io.trino.spi.type.LongTimestampWithTimeZone; 45 | import io.trino.spi.type.MapType; 46 | import io.trino.spi.type.RowType; 47 | import io.trino.spi.type.Type; 48 | import io.trino.spi.type.VarbinaryType; 49 | import io.trino.spi.type.VarcharType; 50 | 51 | import java.io.IOException; 52 | import java.io.UncheckedIOException; 53 | import java.math.BigDecimal; 54 | import java.util.ArrayList; 55 | import java.util.List; 56 | 57 | import static io.airlift.slice.Slices.wrappedBuffer; 58 | import static io.trino.spi.StandardErrorCode.GENERIC_INTERNAL_ERROR; 59 | import static io.trino.spi.type.BigintType.BIGINT; 60 | import static io.trino.spi.type.DateType.DATE; 61 | import static io.trino.spi.type.Decimals.encodeShortScaledValue; 62 | import static io.trino.spi.type.IntegerType.INTEGER; 63 | import static io.trino.spi.type.LongTimestampWithTimeZone.fromEpochMillisAndFraction; 64 | import static io.trino.spi.type.TimeType.TIME_MICROS; 65 | import static io.trino.spi.type.TimeZoneKey.UTC_KEY; 66 | import static io.trino.spi.type.TimestampType.TIMESTAMP_MILLIS; 67 | import static io.trino.spi.type.TimestampWithTimeZoneType.TIMESTAMP_TZ_MILLIS; 68 | import static io.trino.spi.type.Timestamps.MICROSECONDS_PER_MILLISECOND; 69 | import static java.lang.String.format; 70 | import static org.apache.flink.shaded.guava30.com.google.common.base.Verify.verify; 71 | 72 | /** Trino {@link ConnectorPageSource}. */ 73 | public abstract class TrinoPageSourceBase implements ConnectorPageSource { 74 | 75 | private final RecordReader reader; 76 | private final PageBuilder pageBuilder; 77 | private final List columnTypes; 78 | private final List logicalTypes; 79 | 80 | private boolean isFinished = false; 81 | 82 | public TrinoPageSourceBase(RecordReader reader, List projectedColumns) { 83 | this.reader = reader; 84 | this.columnTypes = new ArrayList<>(); 85 | this.logicalTypes = new ArrayList<>(); 86 | for (ColumnHandle handle : projectedColumns) { 87 | TrinoColumnHandle trinoColumnHandle = (TrinoColumnHandle) handle; 88 | columnTypes.add(trinoColumnHandle.getTrinoType()); 89 | logicalTypes.add(trinoColumnHandle.logicalType()); 90 | } 91 | 92 | this.pageBuilder = new PageBuilder(columnTypes); 93 | } 94 | 95 | @Override 96 | public long getCompletedBytes() { 97 | return 0; 98 | } 99 | 100 | @Override 101 | public long getReadTimeNanos() { 102 | return 0; 103 | } 104 | 105 | @Override 106 | public boolean isFinished() { 107 | return isFinished; 108 | } 109 | 110 | @Override 111 | public Page getNextPage() { 112 | return ClassLoaderUtils.runWithContextClassLoader(() -> { 113 | try { 114 | return nextPage(); 115 | } catch (IOException e) { 116 | throw new UncheckedIOException(e); 117 | } 118 | }, TrinoPageSourceBase.class.getClassLoader()); 119 | } 120 | 121 | private Page nextPage() throws IOException { 122 | RecordIterator batch = reader.readBatch(); 123 | if (batch == null) { 124 | isFinished = true; 125 | return null; 126 | } 127 | InternalRow row; 128 | while ((row = batch.next()) != null) { 129 | pageBuilder.declarePosition(); 130 | for (int i = 0; i < columnTypes.size(); i++) { 131 | BlockBuilder output = pageBuilder.getBlockBuilder(i); 132 | appendTo( 133 | columnTypes.get(i), 134 | logicalTypes.get(i), 135 | InternalRowUtils.get(row, i, logicalTypes.get(i)), 136 | output); 137 | } 138 | } 139 | batch.releaseBatch(); 140 | Page page = pageBuilder.build(); 141 | pageBuilder.reset(); 142 | return page; 143 | } 144 | 145 | @Override 146 | public void close() throws IOException { 147 | this.reader.close(); 148 | } 149 | 150 | private void appendTo(Type type, DataType logicalType, Object value, BlockBuilder output) { 151 | if (value == null) { 152 | output.appendNull(); 153 | return; 154 | } 155 | 156 | Class javaType = type.getJavaType(); 157 | if (javaType == boolean.class) { 158 | type.writeBoolean(output, (Boolean) value); 159 | } else if (javaType == long.class) { 160 | if (type.equals(BIGINT)) { 161 | type.writeLong(output, ((Number) value).longValue()); 162 | } else if (type.equals(INTEGER)) { 163 | type.writeLong(output, ((Number) value).intValue()); 164 | } else if (type instanceof DecimalType) { 165 | DecimalType decimalType = (DecimalType) type; 166 | BigDecimal decimal = ((Decimal) value).toBigDecimal(); 167 | type.writeLong(output, encodeShortScaledValue(decimal, decimalType.getScale())); 168 | } else if (type.equals(DATE)) { 169 | type.writeLong(output, (int) value); 170 | } else if (type.equals(TIMESTAMP_MILLIS)) { 171 | type.writeLong( 172 | output, 173 | ((Timestamp) value).getMillisecond() * MICROSECONDS_PER_MILLISECOND); 174 | } else if (type.equals(TIME_MICROS)) { 175 | type.writeLong(output, (int) value * MICROSECONDS_PER_MILLISECOND); 176 | } else { 177 | throw new TrinoException( 178 | GENERIC_INTERNAL_ERROR, 179 | format("Unhandled type for %s: %s", javaType.getSimpleName(), type)); 180 | } 181 | } else if (javaType == double.class) { 182 | type.writeDouble(output, ((Number) value).doubleValue()); 183 | } else if (type instanceof DecimalType) { 184 | writeObject(output, type, value); 185 | } else if (javaType == Slice.class) { 186 | writeSlice(output, type, value); 187 | } else if (javaType == LongTimestampWithTimeZone.class) { 188 | verify(type.equals(TIMESTAMP_TZ_MILLIS)); 189 | Timestamp Timestamp = (Timestamp) value; 190 | type.writeObject( 191 | output, fromEpochMillisAndFraction(Timestamp.getMillisecond(), 0, UTC_KEY)); 192 | } else if (javaType == Block.class) { 193 | writeBlock(output, type, logicalType, value); 194 | } else { 195 | throw new TrinoException( 196 | GENERIC_INTERNAL_ERROR, 197 | format("Unhandled type for %s: %s", javaType.getSimpleName(), type)); 198 | } 199 | } 200 | 201 | private static void writeSlice(BlockBuilder output, Type type, Object value) { 202 | if (type instanceof VarcharType || type instanceof io.trino.spi.type.CharType) { 203 | type.writeSlice(output, wrappedBuffer(((BinaryString) value).toBytes())); 204 | } else if (type instanceof VarbinaryType) { 205 | type.writeSlice(output, wrappedBuffer((byte[]) value)); 206 | } else { 207 | throw new TrinoException( 208 | GENERIC_INTERNAL_ERROR, "Unhandled type for Slice: " + type.getTypeSignature()); 209 | } 210 | } 211 | 212 | private static void writeObject(BlockBuilder output, Type type, Object value) { 213 | if (type instanceof DecimalType) { 214 | DecimalType decimalType = (DecimalType) type; 215 | BigDecimal decimal = ((Decimal) value).toBigDecimal(); 216 | type.writeObject(output, Decimals.encodeScaledValue(decimal, decimalType.getScale())); 217 | } else { 218 | throw new TrinoException( 219 | GENERIC_INTERNAL_ERROR, 220 | "Unhandled type for Object: " + type.getTypeSignature()); 221 | } 222 | } 223 | 224 | private void writeBlock(BlockBuilder output, Type type, DataType logicalType, Object value) { 225 | if (type instanceof ArrayType) { 226 | BlockBuilder builder = output.beginBlockEntry(); 227 | 228 | InternalArray arrayData = (InternalArray) value; 229 | DataType elementType = DataTypeChecks.getNestedTypes(logicalType).get(0); 230 | for (int i = 0; i < arrayData.size(); i++) { 231 | appendTo( 232 | type.getTypeParameters().get(0), 233 | elementType, 234 | InternalRowUtils.get(arrayData, i, elementType), 235 | builder); 236 | } 237 | 238 | output.closeEntry(); 239 | return; 240 | } 241 | if (type instanceof RowType) { 242 | InternalRow rowData = (InternalRow) value; 243 | BlockBuilder builder = output.beginBlockEntry(); 244 | for (int index = 0; index < type.getTypeParameters().size(); index++) { 245 | Type fieldType = type.getTypeParameters().get(index); 246 | DataType fieldLogicalType = 247 | ((org.apache.paimon.types.RowType) logicalType) 248 | .getTypeAt(index); 249 | appendTo( 250 | fieldType, 251 | fieldLogicalType, 252 | InternalRowUtils.get(rowData, index, fieldLogicalType), 253 | builder); 254 | } 255 | output.closeEntry(); 256 | return; 257 | } 258 | if (type instanceof MapType) { 259 | InternalMap mapData = (InternalMap) value; 260 | InternalArray keyArray = mapData.keyArray(); 261 | InternalArray valueArray = mapData.valueArray(); 262 | DataType keyType = ((org.apache.paimon.types.MapType) logicalType).getKeyType(); 263 | DataType valueType = ((org.apache.paimon.types.MapType) logicalType).getValueType(); 264 | BlockBuilder builder = output.beginBlockEntry(); 265 | for (int i = 0; i < keyArray.size(); i++) { 266 | appendTo( 267 | type.getTypeParameters().get(0), 268 | keyType, 269 | InternalRowUtils.get(keyArray, i, keyType), 270 | builder); 271 | appendTo( 272 | type.getTypeParameters().get(1), 273 | valueType, 274 | InternalRowUtils.get(valueArray, i, valueType), 275 | builder); 276 | } 277 | output.closeEntry(); 278 | return; 279 | } 280 | throw new TrinoException( 281 | GENERIC_INTERNAL_ERROR, "Unhandled type for Block: " + type.getTypeSignature()); 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoPageSourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.predicate.TupleDomain; 22 | import org.apache.paimon.CoreOptions; 23 | import org.apache.paimon.table.Table; 24 | import org.apache.paimon.table.source.ReadBuilder; 25 | import org.apache.paimon.types.RowType; 26 | 27 | import io.trino.spi.connector.ColumnHandle; 28 | import io.trino.spi.connector.ConnectorPageSource; 29 | import io.trino.spi.connector.ConnectorPageSourceProvider; 30 | import io.trino.spi.connector.ConnectorSession; 31 | import io.trino.spi.connector.ConnectorSplit; 32 | import io.trino.spi.connector.ConnectorTableHandle; 33 | import io.trino.spi.connector.ConnectorTransactionHandle; 34 | import io.trino.spi.connector.DynamicFilter; 35 | 36 | import java.io.IOException; 37 | import java.util.HashMap; 38 | import java.util.List; 39 | import java.util.Map; 40 | import java.util.stream.Collectors; 41 | 42 | import static org.apache.paimon.trino.ClassLoaderUtils.runWithContextClassLoader; 43 | 44 | /** Trino {@link ConnectorPageSourceProvider}. */ 45 | public class TrinoPageSourceProvider implements ConnectorPageSourceProvider { 46 | 47 | @Override 48 | public ConnectorPageSource createPageSource( 49 | ConnectorTransactionHandle transaction, 50 | ConnectorSession session, 51 | ConnectorSplit split, 52 | ConnectorTableHandle tableHandle, 53 | List columns, 54 | DynamicFilter dynamicFilter) { 55 | TrinoTableHandle trinoTableHandle = (TrinoTableHandle) tableHandle; 56 | Table table = trinoTableHandle.tableWithDynamicOptions(session); 57 | return runWithContextClassLoader( 58 | () -> createPageSource(table, trinoTableHandle.getFilter(), (TrinoSplit) split, columns), 59 | TrinoPageSourceProvider.class.getClassLoader()); 60 | } 61 | 62 | private ConnectorPageSource createPageSource( 63 | Table table, TupleDomain filter, TrinoSplit split, List columns) { 64 | ReadBuilder read = table.newReadBuilder(); 65 | RowType rowType = table.rowType(); 66 | List fieldNames = FieldNameUtils.fieldNames(rowType); 67 | List projectedFields = 68 | columns.stream() 69 | .map(TrinoColumnHandle.class::cast) 70 | .map(TrinoColumnHandle::getColumnName) 71 | .collect(Collectors.toList()); 72 | if (!fieldNames.equals(projectedFields)) { 73 | int[] projected = projectedFields.stream().mapToInt(fieldNames::indexOf).toArray(); 74 | read.withProjection(projected); 75 | } 76 | 77 | new TrinoFilterConverter(rowType) 78 | .convert(filter) 79 | .ifPresent(read::withFilter); 80 | 81 | try { 82 | return new TrinoPageSource(read.newRead().createReader(split.decodeSplit()), columns); 83 | } catch (IOException e) { 84 | throw new RuntimeException(e); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.Plugin; 22 | import io.trino.spi.connector.ConnectorFactory; 23 | 24 | import java.util.Collections; 25 | 26 | /** Trino {@link Plugin}. */ 27 | public class TrinoPlugin implements Plugin { 28 | @Override 29 | public Iterable getConnectorFactories() { 30 | return Collections.singletonList(new TrinoConnectorFactory()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoSplit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.table.source.Split; 22 | 23 | import com.fasterxml.jackson.annotation.JsonCreator; 24 | import com.fasterxml.jackson.annotation.JsonProperty; 25 | import io.trino.spi.HostAddress; 26 | import io.trino.spi.connector.ConnectorSplit; 27 | 28 | import java.util.Collections; 29 | import java.util.List; 30 | 31 | /** Trino {@link ConnectorSplit}. */ 32 | public class TrinoSplit implements ConnectorSplit { 33 | 34 | private final String splitSerialized; 35 | 36 | @JsonCreator 37 | public TrinoSplit(@JsonProperty("splitSerialized") String splitSerialized) { 38 | this.splitSerialized = splitSerialized; 39 | } 40 | 41 | public static TrinoSplit fromSplit(Split split) { 42 | return new TrinoSplit(EncodingUtils.encodeObjectToString(split)); 43 | } 44 | 45 | public Split decodeSplit() { 46 | return EncodingUtils.decodeStringToObject(splitSerialized); 47 | } 48 | 49 | @JsonProperty 50 | public String getSplitSerialized() { 51 | return splitSerialized; 52 | } 53 | 54 | @Override 55 | public boolean isRemotelyAccessible() { 56 | return true; 57 | } 58 | 59 | @Override 60 | public List getAddresses() { 61 | return Collections.emptyList(); 62 | } 63 | 64 | @Override 65 | public Object getInfo() { 66 | return Collections.emptyMap(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoSplitManagerBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorSession; 22 | import org.apache.paimon.table.Table; 23 | import org.apache.paimon.table.source.ReadBuilder; 24 | import org.apache.paimon.table.source.Split; 25 | import org.apache.paimon.table.source.TableScan; 26 | 27 | import io.trino.spi.connector.ConnectorSplitManager; 28 | import io.trino.spi.connector.ConnectorSplitSource; 29 | import io.trino.spi.connector.ConnectorTableHandle; 30 | 31 | import java.util.List; 32 | import java.util.stream.Collectors; 33 | 34 | /** Trino {@link ConnectorSplitManager}. */ 35 | public abstract class TrinoSplitManagerBase implements ConnectorSplitManager { 36 | 37 | protected ConnectorSplitSource getSplits( 38 | ConnectorTableHandle connectorTableHandle, ConnectorSession session) { 39 | // TODO dynamicFilter? 40 | // TODO what is constraint? 41 | 42 | TrinoTableHandle tableHandle = (TrinoTableHandle) connectorTableHandle; 43 | Table table = tableHandle.tableWithDynamicOptions(session); 44 | ReadBuilder readBuilder = table.newReadBuilder(); 45 | new TrinoFilterConverter(table.rowType()) 46 | .convert(tableHandle.getFilter()) 47 | .ifPresent(readBuilder::withFilter); 48 | List splits = readBuilder.newScan().plan().splits(); 49 | return new TrinoSplitSource( 50 | splits.stream().map(TrinoSplit::fromSplit).collect(Collectors.toList())); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoSplitSourceBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorSplit; 22 | import io.trino.spi.connector.ConnectorSplitSource; 23 | 24 | import java.util.ArrayList; 25 | import java.util.LinkedList; 26 | import java.util.List; 27 | import java.util.Queue; 28 | import java.util.concurrent.CompletableFuture; 29 | 30 | /** Trino {@link ConnectorSplitSource}. */ 31 | public abstract class TrinoSplitSourceBase implements ConnectorSplitSource { 32 | 33 | private final Queue splits; 34 | 35 | public TrinoSplitSourceBase(List splits) { 36 | this.splits = new LinkedList<>(splits); 37 | } 38 | 39 | protected CompletableFuture innerGetNextBatch(int maxSize) { 40 | List batch = new ArrayList<>(); 41 | for (int i = 0; i < maxSize; i++) { 42 | TrinoSplit split = splits.poll(); 43 | if (split == null) { 44 | break; 45 | } 46 | batch.add(split); 47 | } 48 | return CompletableFuture.completedFuture(new ConnectorSplitBatch(batch, isFinished())); 49 | } 50 | 51 | @Override 52 | public void close() {} 53 | 54 | @Override 55 | public boolean isFinished() { 56 | return splits.isEmpty(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoTableHandle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.connector.ConnectorSession; 22 | import org.apache.paimon.CoreOptions; 23 | import org.apache.paimon.table.Table; 24 | import org.apache.paimon.utils.InstantiationUtil; 25 | 26 | import com.fasterxml.jackson.annotation.JsonCreator; 27 | import com.fasterxml.jackson.annotation.JsonProperty; 28 | import io.trino.spi.connector.ColumnHandle; 29 | import io.trino.spi.connector.ColumnMetadata; 30 | import io.trino.spi.connector.ConnectorTableHandle; 31 | import io.trino.spi.connector.ConnectorTableMetadata; 32 | import io.trino.spi.connector.SchemaTableName; 33 | import io.trino.spi.predicate.TupleDomain; 34 | 35 | import java.io.IOException; 36 | import java.util.Arrays; 37 | import java.util.Collections; 38 | import java.util.HashMap; 39 | import java.util.List; 40 | import java.util.Map; 41 | import java.util.Objects; 42 | import java.util.Optional; 43 | import java.util.stream.Collectors; 44 | 45 | /** Trino {@link ConnectorTableHandle}. */ 46 | public final class TrinoTableHandle implements ConnectorTableHandle { 47 | 48 | public static final String SCAN_TIMESTAMP = "scan_timestamp_millis"; 49 | public static final String SCAN_SNAPSHOT = "scan_snapshot_id"; 50 | 51 | private final String schemaName; 52 | private final String tableName; 53 | private final byte[] serializedTable; 54 | private final TupleDomain filter; 55 | private final Optional> projectedColumns; 56 | 57 | private Table lazyTable; 58 | 59 | public TrinoTableHandle( 60 | String schemaName, String tableName, byte[] serializedTable) { 61 | this(schemaName, tableName, serializedTable, TupleDomain.all(), Optional.empty()); 62 | } 63 | 64 | @JsonCreator 65 | public TrinoTableHandle( 66 | @JsonProperty("schemaName") String schemaName, 67 | @JsonProperty("tableName") String tableName, 68 | @JsonProperty("serializedTable") byte[] serializedTable, 69 | @JsonProperty("filter") TupleDomain filter, 70 | @JsonProperty("projection") Optional> projectedColumns) { 71 | this.schemaName = schemaName; 72 | this.tableName = tableName; 73 | this.serializedTable = serializedTable; 74 | this.filter = filter; 75 | this.projectedColumns = projectedColumns; 76 | } 77 | 78 | @JsonProperty 79 | public String getSchemaName() { 80 | return schemaName; 81 | } 82 | 83 | @JsonProperty 84 | public String getTableName() { 85 | return tableName; 86 | } 87 | 88 | @JsonProperty 89 | public byte[] getSerializedTable() { 90 | return serializedTable; 91 | } 92 | 93 | @JsonProperty 94 | public TupleDomain getFilter() { 95 | return filter; 96 | } 97 | 98 | @JsonProperty 99 | public Optional> getProjectedColumns() { 100 | return projectedColumns; 101 | } 102 | 103 | public TrinoTableHandle copy(TupleDomain filter) { 104 | return new TrinoTableHandle( 105 | schemaName, tableName, serializedTable, filter, projectedColumns); 106 | } 107 | 108 | public TrinoTableHandle copy(Optional> projectedColumns) { 109 | return new TrinoTableHandle( 110 | schemaName, tableName, serializedTable, filter, projectedColumns); 111 | } 112 | 113 | public Table tableWithDynamicOptions(ConnectorSession session) { 114 | // see TrinoConnector.getSessionProperties 115 | Map dynamicOptions = new HashMap<>(); 116 | Long scanTimestampMills = session.getProperty(SCAN_TIMESTAMP, Long.class); 117 | if (scanTimestampMills != null) { 118 | dynamicOptions.put(CoreOptions.SCAN_TIMESTAMP_MILLIS.key(), scanTimestampMills.toString()); 119 | } 120 | Long scanSnapshotId = session.getProperty(SCAN_SNAPSHOT, Long.class); 121 | if (scanSnapshotId != null) { 122 | dynamicOptions.put(CoreOptions.SCAN_SNAPSHOT_ID.key(), scanSnapshotId.toString()); 123 | } 124 | 125 | return dynamicOptions.size() > 0 ? 126 | table().copy(dynamicOptions) : 127 | table(); 128 | } 129 | 130 | public Table table() { 131 | if (lazyTable == null) { 132 | try { 133 | lazyTable = InstantiationUtil.deserializeObject(serializedTable, this.getClass().getClassLoader()); 134 | } catch (IOException | ClassNotFoundException e) { 135 | throw new RuntimeException(e); 136 | } 137 | } 138 | return lazyTable; 139 | } 140 | 141 | public ConnectorTableMetadata tableMetadata() { 142 | return new ConnectorTableMetadata( 143 | SchemaTableName.schemaTableName(schemaName, tableName), 144 | columnMetadatas(), 145 | Collections.emptyMap(), 146 | Optional.empty()); 147 | } 148 | 149 | public List columnMetadatas() { 150 | return table().rowType().getFields().stream() 151 | .map( 152 | column -> 153 | ColumnMetadata.builder() 154 | .setName(column.name()) 155 | .setType( 156 | TrinoTypeUtils.fromFlinkType( 157 | column.type())) 158 | .setNullable(column.type().isNullable()) 159 | .setComment(Optional.ofNullable(column.description())) 160 | .build()) 161 | .collect(Collectors.toList()); 162 | } 163 | 164 | public TrinoColumnHandle columnHandle(String field) { 165 | List fieldNames = FieldNameUtils.fieldNames(table().rowType()); 166 | int index = fieldNames.indexOf(field); 167 | if (index == -1) { 168 | throw new RuntimeException(String.format("Cannot find field %s in schema %s", field, fieldNames)); 169 | } 170 | return TrinoColumnHandle.of(field, table().rowType().getTypeAt(index)); 171 | } 172 | 173 | @Override 174 | public boolean equals(Object o) { 175 | if (this == o) { 176 | return true; 177 | } 178 | if (o == null || getClass() != o.getClass()) { 179 | return false; 180 | } 181 | TrinoTableHandle that = (TrinoTableHandle) o; 182 | return Arrays.equals(serializedTable, that.serializedTable) 183 | && Objects.equals(schemaName, that.schemaName) 184 | && Objects.equals(tableName, that.tableName) 185 | && Objects.equals(filter, that.filter) 186 | && Objects.equals(projectedColumns, that.projectedColumns); 187 | } 188 | 189 | @Override 190 | public int hashCode() { 191 | return Objects.hash( 192 | schemaName, 193 | tableName, 194 | filter, 195 | projectedColumns, 196 | Arrays.hashCode(serializedTable)); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoTransactionHandle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | package org.apache.paimon.trino; 16 | 17 | import io.trino.spi.connector.ConnectorTransactionHandle; 18 | 19 | /** An empty transaction handle. */ 20 | public enum TrinoTransactionHandle implements ConnectorTransactionHandle { 21 | INSTANCE 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/apache/paimon/trino/TrinoTypeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import io.trino.spi.type.BigintType; 22 | import io.trino.spi.type.IntegerType; 23 | import io.trino.spi.type.RealType; 24 | import io.trino.spi.type.SmallintType; 25 | import io.trino.spi.type.TimestampWithTimeZoneType; 26 | import io.trino.spi.type.TinyintType; 27 | import io.trino.spi.type.Type; 28 | import io.trino.spi.type.TypeOperators; 29 | import io.trino.spi.type.VarbinaryType; 30 | import io.trino.spi.type.VarcharType; 31 | 32 | import org.apache.paimon.types.ArrayType; 33 | import org.apache.paimon.types.BigIntType; 34 | import org.apache.paimon.types.BinaryType; 35 | import org.apache.paimon.types.BooleanType; 36 | import org.apache.paimon.types.CharType; 37 | import org.apache.paimon.types.DataType; 38 | import org.apache.paimon.types.DataTypeDefaultVisitor; 39 | import org.apache.paimon.types.DateType; 40 | import org.apache.paimon.types.DecimalType; 41 | import org.apache.paimon.types.DoubleType; 42 | import org.apache.paimon.types.FloatType; 43 | import org.apache.paimon.types.IntType; 44 | import org.apache.paimon.types.LocalZonedTimestampType; 45 | import org.apache.paimon.types.MapType; 46 | import org.apache.paimon.types.MultisetType; 47 | import org.apache.paimon.types.RowType; 48 | import org.apache.paimon.types.SmallIntType; 49 | import org.apache.paimon.types.TimeType; 50 | import org.apache.paimon.types.TimestampType; 51 | import org.apache.paimon.types.TinyIntType; 52 | import org.apache.paimon.types.VarBinaryType; 53 | import org.apache.paimon.types.VarCharType; 54 | 55 | 56 | import java.util.List; 57 | import java.util.stream.Collectors; 58 | 59 | /** Trino type from Flink Type. */ 60 | public class TrinoTypeUtils { 61 | 62 | public static Type fromFlinkType(DataType type) { 63 | return type.accept(FlinkToTrinoTypeVistor.INSTANCE); 64 | } 65 | 66 | private static class FlinkToTrinoTypeVistor extends DataTypeDefaultVisitor { 67 | 68 | private static final FlinkToTrinoTypeVistor INSTANCE = new FlinkToTrinoTypeVistor(); 69 | 70 | @Override 71 | public Type visit(CharType charType) { 72 | return io.trino.spi.type.CharType.createCharType( 73 | Math.min(io.trino.spi.type.CharType.MAX_LENGTH, charType.getLength())); 74 | } 75 | 76 | @Override 77 | public Type visit(VarCharType varCharType) { 78 | if (varCharType.getLength() == VarCharType.MAX_LENGTH) { 79 | return VarcharType.createUnboundedVarcharType(); 80 | } 81 | return VarcharType.createVarcharType( 82 | Math.min(VarcharType.MAX_LENGTH, varCharType.getLength())); 83 | } 84 | 85 | @Override 86 | public Type visit(BooleanType booleanType) { 87 | return io.trino.spi.type.BooleanType.BOOLEAN; 88 | } 89 | 90 | @Override 91 | public Type visit(BinaryType binaryType) { 92 | return VarbinaryType.VARBINARY; 93 | } 94 | 95 | @Override 96 | public Type visit(VarBinaryType varBinaryType) { 97 | return VarbinaryType.VARBINARY; 98 | } 99 | 100 | @Override 101 | public Type visit(DecimalType decimalType) { 102 | return io.trino.spi.type.DecimalType.createDecimalType(decimalType.getPrecision(), decimalType.getScale()); 103 | } 104 | 105 | @Override 106 | public Type visit(TinyIntType tinyIntType) { 107 | return TinyintType.TINYINT; 108 | } 109 | 110 | @Override 111 | public Type visit(SmallIntType smallIntType) { 112 | return SmallintType.SMALLINT; 113 | } 114 | 115 | @Override 116 | public Type visit(IntType intType) { 117 | return IntegerType.INTEGER; 118 | } 119 | 120 | @Override 121 | public Type visit(BigIntType bigIntType) { 122 | return BigintType.BIGINT; 123 | } 124 | 125 | @Override 126 | public Type visit(FloatType floatType) { 127 | return RealType.REAL; 128 | } 129 | 130 | @Override 131 | public Type visit(DoubleType doubleType) { 132 | return io.trino.spi.type.DoubleType.DOUBLE; 133 | } 134 | 135 | @Override 136 | public Type visit(DateType dateType) { 137 | return io.trino.spi.type.DateType.DATE; 138 | } 139 | 140 | @Override 141 | public Type visit(TimeType timeType) { 142 | return io.trino.spi.type.TimeType.TIME_MILLIS; 143 | } 144 | 145 | @Override 146 | public Type visit(TimestampType timestampType) { 147 | return io.trino.spi.type.TimestampType.TIMESTAMP_MILLIS; 148 | } 149 | 150 | @Override 151 | public Type visit(LocalZonedTimestampType localZonedTimestampType) { 152 | return TimestampWithTimeZoneType.TIMESTAMP_TZ_MILLIS; 153 | } 154 | 155 | @Override 156 | public Type visit(ArrayType arrayType) { 157 | DataType elementType = arrayType.getElementType(); 158 | return new io.trino.spi.type.ArrayType(elementType.accept(this)); 159 | } 160 | 161 | @Override 162 | public Type visit(MultisetType multisetType) { 163 | return new MapType(multisetType.getElementType(), new IntType()).accept(this); 164 | } 165 | 166 | @Override 167 | public Type visit(MapType mapType) { 168 | return new io.trino.spi.type.MapType( 169 | mapType.getKeyType().accept(this), 170 | mapType.getValueType().accept(this), 171 | new TypeOperators()); 172 | } 173 | 174 | @Override 175 | public Type visit(RowType rowType) { 176 | List fields = 177 | rowType.getFields().stream() 178 | .map( 179 | field -> 180 | io.trino.spi.type.RowType.field( 181 | field.name(), field.type().accept(this))) 182 | .collect(Collectors.toList()); 183 | return io.trino.spi.type.RowType.from(fields); 184 | } 185 | 186 | @Override 187 | protected Type defaultMethod(DataType logicalType) { 188 | throw new UnsupportedOperationException("Unsupported type: " + logicalType); 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/io.trino.spi.Plugin: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | org.apache.paimon.trino.TrinoPlugin 17 | -------------------------------------------------------------------------------- /src/test/java/org/apache/paimon/trino/SimpleTableTestHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.data.InternalRow; 22 | import org.apache.paimon.schema.Schema; 23 | import org.apache.paimon.schema.SchemaManager; 24 | import org.apache.paimon.fs.Path; 25 | import org.apache.paimon.fs.local.LocalFileIO; 26 | import org.apache.paimon.table.FileStoreTable; 27 | import org.apache.paimon.table.FileStoreTableFactory; 28 | import org.apache.paimon.table.sink.InnerTableCommit; 29 | import org.apache.paimon.table.sink.InnerTableWrite; 30 | import org.apache.paimon.types.RowType; 31 | 32 | import java.util.Collections; 33 | import java.util.HashMap; 34 | 35 | /** A simple table test helper to write and commit. */ 36 | public class SimpleTableTestHelper { 37 | 38 | private final InnerTableWrite writer; 39 | private final InnerTableCommit commit; 40 | 41 | public SimpleTableTestHelper(Path path, RowType rowType) throws Exception { 42 | new SchemaManager(LocalFileIO.create(), path) 43 | .createTable( 44 | new Schema( 45 | rowType.getFields(), 46 | Collections.emptyList(), 47 | Collections.emptyList(), 48 | new HashMap<>(), 49 | "")); 50 | FileStoreTable table = FileStoreTableFactory.create(LocalFileIO.create(), path); 51 | String user = "user"; 52 | this.writer = table.newWrite(user); 53 | this.commit = table.newCommit(user); 54 | } 55 | 56 | public void write(InternalRow row) throws Exception { 57 | writer.write(row); 58 | } 59 | 60 | public void commit() throws Exception { 61 | commit.commit(0, writer.prepareCommit(true, 0)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/org/apache/paimon/trino/TestTrinoITCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package org.apache.paimon.trino; 20 | 21 | import org.apache.paimon.data.BinaryString; 22 | import org.apache.paimon.data.GenericMap; 23 | import org.apache.paimon.data.GenericRow; 24 | import org.apache.paimon.schema.Schema; 25 | import org.apache.paimon.schema.SchemaManager; 26 | import org.apache.paimon.fs.Path; 27 | import org.apache.paimon.fs.local.LocalFileIO; 28 | import org.apache.paimon.table.FileStoreTable; 29 | import org.apache.paimon.table.FileStoreTableFactory; 30 | import org.apache.paimon.table.sink.InnerTableCommit; 31 | import org.apache.paimon.table.sink.InnerTableWrite; 32 | import org.apache.paimon.table.sink.TableCommit; 33 | import org.apache.paimon.table.sink.TableWrite; 34 | import org.apache.paimon.types.BigIntType; 35 | import org.apache.paimon.types.CharType; 36 | import org.apache.paimon.types.DataField; 37 | import org.apache.paimon.types.DataTypes; 38 | import org.apache.paimon.types.IntType; 39 | import org.apache.paimon.types.MapType; 40 | import org.apache.paimon.types.RowKind; 41 | import org.apache.paimon.types.RowType; 42 | import org.apache.paimon.types.VarCharType; 43 | 44 | import io.trino.testing.AbstractTestQueryFramework; 45 | import io.trino.testing.DistributedQueryRunner; 46 | import io.trino.testing.MaterializedResult; 47 | import io.trino.testing.QueryRunner; 48 | import org.testng.annotations.Test; 49 | 50 | import java.nio.file.Files; 51 | import java.util.Arrays; 52 | import java.util.Collections; 53 | import java.util.HashMap; 54 | import java.util.Map; 55 | import java.util.UUID; 56 | 57 | import static io.airlift.testing.Closeables.closeAllSuppress; 58 | import static io.trino.testing.TestingSession.testSessionBuilder; 59 | import static org.apache.paimon.data.BinaryString.fromString; 60 | import static org.assertj.core.api.Assertions.assertThat; 61 | 62 | /** ITCase for trino connector. */ 63 | public class TestTrinoITCase extends AbstractTestQueryFramework { 64 | 65 | private static final String CATALOG = "paimon"; 66 | private static final String DB = "default"; 67 | 68 | @Override 69 | protected QueryRunner createQueryRunner() throws Exception { 70 | String warehouse = 71 | Files.createTempDirectory(UUID.randomUUID().toString()).toUri().toString(); 72 | // flink sink 73 | Path tablePath1 = new Path(warehouse, DB + ".db/t1"); 74 | SimpleTableTestHelper testHelper1 = createTestHelper(tablePath1); 75 | testHelper1.write(GenericRow.of(1, 2L, fromString("1"), fromString("1"))); 76 | testHelper1.write(GenericRow.of(3, 4L, fromString("2"), fromString("2"))); 77 | testHelper1.write(GenericRow.of(5, 6L, fromString("3"), fromString("3"))); 78 | testHelper1.write(GenericRow.ofKind(RowKind.DELETE, 3, 4L, fromString("2"), fromString("2"))); 79 | testHelper1.commit(); 80 | 81 | Path tablePath2 = new Path(warehouse, "default.db/t2"); 82 | SimpleTableTestHelper testHelper2 = createTestHelper(tablePath2); 83 | testHelper2.write(GenericRow.of(1, 2L, fromString("1"), fromString("1"))); 84 | testHelper2.write(GenericRow.of(3, 4L, fromString("2"), fromString("2"))); 85 | testHelper2.commit(); 86 | testHelper2.write(GenericRow.of(5, 6L, fromString("3"), fromString("3"))); 87 | testHelper2.write(GenericRow.of(7, 8L, fromString("4"), fromString("4"))); 88 | testHelper2.commit(); 89 | 90 | { 91 | Path tablePath3 = new Path(warehouse, "default.db/t3"); 92 | RowType rowType = 93 | new RowType( 94 | Arrays.asList( 95 | new DataField(0, "pt", DataTypes.STRING()), 96 | new DataField(1, "a", new IntType()), 97 | new DataField(2, "b", new BigIntType()), 98 | new DataField(3, "c", new BigIntType()), 99 | new DataField(4, "d", new IntType()))); 100 | new SchemaManager(LocalFileIO.create(), tablePath3) 101 | .createTable( 102 | new Schema( 103 | rowType.getFields(), 104 | Collections.singletonList("pt"), 105 | Collections.emptyList(), 106 | new HashMap<>(), 107 | "")); 108 | FileStoreTable table = FileStoreTableFactory.create(LocalFileIO.create(), tablePath3); 109 | InnerTableWrite writer = table.newWrite("user"); 110 | InnerTableCommit commit = table.newCommit("user"); 111 | writer.write(GenericRow.of(fromString("1"), 1, 1L, 1L, 1)); 112 | writer.write(GenericRow.of(fromString("1"), 1, 2L, 2L, 2)); 113 | writer.write(GenericRow.of(fromString("2"), 3, 3L, 3L, 3)); 114 | commit.commit(0, writer.prepareCommit(true, 0)); 115 | } 116 | 117 | { 118 | Path tablePath4 = new Path(warehouse, "default.db/t4"); 119 | RowType rowType = 120 | new RowType( 121 | Arrays.asList( 122 | new DataField(0, "i", new IntType()), 123 | new DataField(1, "map", new MapType(new VarCharType(VarCharType.MAX_LENGTH), new VarCharType(VarCharType.MAX_LENGTH))) 124 | )); 125 | new SchemaManager(LocalFileIO.create(), tablePath4) 126 | .createTable( 127 | new Schema( 128 | rowType.getFields(), 129 | Collections.emptyList(), 130 | Collections.singletonList("i"), 131 | new HashMap<>(), 132 | "")); 133 | FileStoreTable table = FileStoreTableFactory.create(LocalFileIO.create(), tablePath4); 134 | InnerTableWrite writer = table.newWrite("user"); 135 | InnerTableCommit commit = table.newCommit("user"); 136 | writer.write(GenericRow.of(1, new GenericMap(new HashMap<>() { 137 | { 138 | put(fromString("1"), fromString("2")); 139 | } 140 | }))); 141 | commit.commit(0, writer.prepareCommit(true, 0)); 142 | } 143 | 144 | DistributedQueryRunner queryRunner = null; 145 | try { 146 | queryRunner = 147 | DistributedQueryRunner.builder( 148 | testSessionBuilder().setCatalog(CATALOG).setSchema(DB).build()) 149 | .build(); 150 | queryRunner.installPlugin(new TrinoPlugin()); 151 | Map options = new HashMap<>(); 152 | options.put("warehouse", warehouse); 153 | queryRunner.createCatalog(CATALOG, CATALOG, options); 154 | return queryRunner; 155 | } catch (Throwable e) { 156 | closeAllSuppress(e, queryRunner); 157 | throw e; 158 | } 159 | } 160 | 161 | private static SimpleTableTestHelper createTestHelper(Path tablePath) throws Exception { 162 | RowType rowType = 163 | new RowType( 164 | Arrays.asList( 165 | new DataField(0, "a", new IntType()), 166 | new DataField(1, "b", new BigIntType()), 167 | // test field name has upper case 168 | new DataField(2, "aCa", new VarCharType()), 169 | new DataField(3, "d", new CharType(1)) 170 | )); 171 | return new SimpleTableTestHelper(tablePath, rowType); 172 | } 173 | 174 | @Test 175 | public void testComplexTypes() { 176 | assertThat(sql("SELECT * FROM paimon.default.t4")).isEqualTo("[[1, {1=2}]]"); 177 | } 178 | 179 | @Test 180 | public void testProjection() { 181 | assertThat(sql("SELECT * FROM paimon.default.t1")).isEqualTo("[[1, 2, 1, 1], [5, 6, 3, 3]]"); 182 | assertThat(sql("SELECT a, aCa FROM paimon.default.t1")).isEqualTo("[[1, 1], [5, 3]]"); 183 | assertThat(sql("SELECT SUM(b) FROM paimon.default.t1")).isEqualTo("[[8]]"); 184 | } 185 | 186 | @Test 187 | public void testSystemTable() { 188 | assertThat(sql("SELECT snapshot_id,schema_id,commit_user,commit_identifier,commit_kind FROM \"t1$snapshots\"")).isEqualTo("[[1, 0, user, 0, APPEND]]"); 189 | } 190 | 191 | @Test 192 | public void testFilter() { 193 | assertThat(sql("SELECT a, aCa FROM paimon.default.t2 WHERE a < 4")) 194 | .isEqualTo("[[1, 1], [3, 2]]"); 195 | } 196 | 197 | @Test 198 | public void testGroupByWithCast() { 199 | assertThat(sql("SELECT pt, a, SUM(b), SUM(d) FROM paimon.default.t3 GROUP BY pt, a ORDER BY pt, a")) 200 | .isEqualTo("[[1, 1, 3, 3], [2, 3, 3, 3]]"); 201 | } 202 | 203 | @Test 204 | public void testShowCreateTable() { 205 | assertThat(sql("SHOW CREATE TABLE paimon.default.t3")) 206 | .isEqualTo("[[CREATE TABLE paimon.default.t3 (\n" + 207 | " pt varchar,\n" + 208 | " a integer,\n" + 209 | " b bigint,\n" + 210 | " c bigint,\n" + 211 | " d integer\n" + 212 | ")]]"); 213 | } 214 | 215 | private String sql(String sql) { 216 | MaterializedResult result = getQueryRunner().execute(sql); 217 | return result.getMaterializedRows().toString(); 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /src/test/resources/log4j2-test.properties: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | ################################################################################ 18 | 19 | # Set root logger level to OFF to not flood build logs 20 | # set manually to INFO for debugging purposes 21 | rootLogger.level = OFF 22 | rootLogger.appenderRef.test.ref = TestLogger 23 | 24 | appender.testlogger.name = TestLogger 25 | appender.testlogger.type = CONSOLE 26 | appender.testlogger.target = SYSTEM_ERR 27 | appender.testlogger.layout.type = PatternLayout 28 | appender.testlogger.layout.pattern = %-4r [%t] %-5p %c %x - %m%n 29 | 30 | logger.kafka.name = kafka 31 | logger.kafka.level = OFF 32 | logger.kafka2.name = state.change 33 | logger.kafka2.level = OFF 34 | 35 | logger.zookeeper.name = org.apache.zookeeper 36 | logger.zookeeper.level = OFF 37 | logger.I0Itec.name = org.I0Itec 38 | logger.I0Itec.level = OFF 39 | --------------------------------------------------------------------------------