Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
77d72c9
Version bump to 1.1.0 (#11)
MrRahulSharma Nov 30, 2022
75a10c9
Bumping the plugin version to 1.1.1-SNAPSHOT (#10)
MrRahulSharma Nov 30, 2022
9ef53ef
Fixed null output schema
Sep 17, 2023
75c1ac0
Merge pull request #16 from cloudsufi/cdap-1682
vikasrathee-cs Sep 21, 2023
3b7d484
Bumping the plugin version to 1.1.1
Sep 21, 2023
4801fc8
Merge pull request #17 from cloudsufi/release/1.1
vikasrathee-cs Sep 21, 2023
388ffe8
bump up from 1.1.1 to 1.1.2-SNAPSHOT
vikasrathee-cs Dec 4, 2023
8bcb39f
Merge pull request #19 from data-integrations/bumpup-to-1.1.2-SNAPSHOT
vikasrathee-cs Dec 4, 2023
ab5d2c9
added support for timestamp_tz datatype.
vikasrathee-cs Nov 16, 2023
553189b
Merge pull request #20 from cloudsufi/cherrypick-timestamp-fix
vikasrathee-cs Dec 4, 2023
2dc31af
Upgrading the driver version from 3.13.24 to 3.14.4
vikasrathee-cs Dec 21, 2023
1b825cb
Merge pull request #28 from cloudsufi/cherrypick-oauth-3.14.4
vikasrathee-cs Jan 4, 2024
4f76380
bump up from 1.1.2-SNAPSHOT to 1.1.2
vikasrathee-cs Jan 4, 2024
17b6925
Merge pull request #29 from data-integrations/bump-up-1.1.2
vikasrathee-cs Jan 4, 2024
c2ada2d
bump up to 1.1.3-SNAPSHOT
vikasrathee-cs Jan 4, 2024
bc1a68c
Merge pull request #31 from data-integrations/bump-up-to-1.1.3-SNAPSHOT
vikasrathee-cs Sep 26, 2024
98681e3
Fix added to override schema
vikasrathee-cs Sep 27, 2024
41813c6
Added unit test cases flow for build.
vikasrathee-cs Sep 27, 2024
82b77d1
Merge pull request #35 from cloudsufi/override-schema-release
vikasrathee-cs Oct 3, 2024
5e3c487
bump up to 1.1.3 Snapshot
vikasrathee-cs Oct 3, 2024
3b340b9
Merge pull request #36 from cloudsufi/bump-up-1.1.3
vikasrathee-cs Oct 3, 2024
b5c9d96
Added fix for decimal issue not having rounding mode and made escape …
vikasrathee-cs Nov 8, 2024
f7d8d0a
bump up to 1.1.4-SNAPSHOT
vikasrathee-cs Nov 12, 2024
2b7f72e
Merge pull request #38 from cloudsufi/snowflake-fixes
vikasrathee-cs Nov 15, 2024
14283e4
bump up to 1.1.4
vikasrathee-cs Nov 15, 2024
5295fd5
Merge pull request #39 from cloudsufi/bump-up-1.1.4
vikasrathee-cs Nov 19, 2024
c72b744
Bump version to 1.11.5-SNAPSHOT for snowflake plugin release
sgarg-CS Jun 2, 2025
d6b222a
Merge pull request #49 from cloudsufi/bump/1.11.5-SNAPSHOT
sgarg-CS Jun 2, 2025
ed8e1ea
PLUGIN-1883: Fetch schema using Named Table in SnowFlake Plugin and P…
sgarg-CS Apr 21, 2025
753b7b9
Merge pull request #51 from cloudsufi/cloudsuficherry-pick/9d8bc2caae…
sgarg-CS Jun 10, 2025
4e3a422
CDAP OSS migration
Jul 9, 2025
98be1c0
Merge pull request #57 from data-integrations/cherry-pick-610/b295b5b…
Aug 19, 2025
0589aaf
Update Snowflake JDBC driver to 4.0.2 and adapt API changes
harishhk107 Apr 8, 2026
1d4b3e0
bump to 1.1.5
harishhk107 Jun 22, 2026
7abb1ca
Update Snowflake JDBC driver to 4.3.4
vishwasvaidya-cloudsufi Oct 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/build-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright © 2024 Cask Data, Inc.
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
# Note: Any changes to this workflow would be used only after merging into develop
name: Build Unit Tests Report

on:
workflow_run:
workflows:
- Build with unit tests
types:
- completed

jobs:
build:
runs-on: ubuntu-latest

if: ${{ github.event.workflow_run.conclusion != 'skipped' }}

steps:
# Pinned 1.0.0 version
- uses: marocchino/action-workflow_run-status@54b6e87d6cb552fc5f36dbe9a722a6048725917a

- name: Download artifact
uses: actions/download-artifact@v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
path: artifacts/

- name: Surefire Report
# Pinned 3.5.2 version
uses: mikepenz/action-junit-report@16a9560bd02f11e7e3bf6b3e2ef6bba6c9d07c32
if: always()
with:
report_paths: '**/target/surefire-reports/TEST-*.xml'
github_token: ${{ secrets.GITHUB_TOKEN }}
detailed_summary: true
commit: ${{ github.event.workflow_run.head_sha }}
check_name: Build Test Report
59 changes: 59 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright © 2024 Cask Data, Inc.
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
# Note: Any changes to this workflow would be used only after merging into develop
name: Build with unit tests

on:
push:
branches: [ develop, release/** ]
pull_request:
branches: [ develop, release/** ]
types: [opened, synchronize, reopened, labeled]

jobs:
build:
runs-on: k8s-runner-build

# We allow builds:
# 1) When it's a merge into a branch
# 2) For PRs that are labeled as build and
# - It's a code change
# - A build label was just added
# A bit complex, but prevents builds when other labels are manipulated
if: >
github.event_name == 'push'
|| (contains(github.event.pull_request.labels.*.name, 'build')
&& (github.event.action != 'labeled' || github.event.label.name == 'build')
)
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.workflow_run.head_sha }}
- name: Cache
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ github.workflow }}-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-${{ github.workflow }}
- name: Build with Maven
run: mvn clean test -fae -T 2 -B -V -DcloudBuild -Dmaven.wagon.http.retryHandler.count=3 -Dmaven.wagon.httpconnectionManager.ttlSeconds=25
- name: Archive build artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: reports-${{ github.run_id }}
path: |
**/target/rat.txt
**/target/surefire-reports/*
10 changes: 6 additions & 4 deletions docs/Snowflake-batchsource.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ log in to Snowflake, minus the "snowflakecomputing.com"). E.g. "myaccount.us-cen

**Role:** Role to use (e.g. `ACCOUNTADMIN`).

**Import Query:** Query for data import.
**Import Query Type** - Method used to retrieve schema from the source.
* **Table Name**: The name of the table to retrieve the schema.
* **Import Query**: Query for data import.

### Credentials

Expand Down Expand Up @@ -68,7 +70,7 @@ Data Types Mapping
----------

| Snowflake Data Types | CDAP Schema Data Type | Comment |
| ------------------------------ | --------------------- | --------------------------------------------------------- |
| ------------------------------ |-----------------------| --------------------------------------------------------- |
| NUMBER | decimal | Default precision and scale are (38,0). |
| DECIMAL | decimal | Synonymous with NUMBER. |
| NUMERIC | decimal | Synonymous with NUMBER. |
Expand All @@ -87,10 +89,10 @@ Data Types Mapping
| DATE | date | |
| DATETIME | timestamp | Alias for TIMESTAMP_NTZ |
| TIME | time | |
| TIMESTAMP | timestamp/string | Alias for one of the TIMESTAMP variations (TIMESTAMP_NTZ by default).|
| TIMESTAMP | timestamp | Alias for one of the TIMESTAMP variations (TIMESTAMP_NTZ by default).|
| TIMESTAMP_LTZ | timestamp | TIMESTAMP with local time zone; time zone, if provided, is not stored.|
| TIMESTAMP_NTZ | timestamp | TIMESTAMP with no time zone; time zone, if provided, is not stored.|
| TIMESTAMP_TZ | string | TIMESTAMP with time zone. |
| TIMESTAMP_TZ | timestamp | TIMESTAMP with time zone. |
| VARIANT | string | A tagged universal type, which can store values of any other type, including OBJECT and ARRAY, up to a maximum size of 16 MB compressed. |
| OBJECT | string | This will return a json with the data |
| ARRAY | string | This will return a json with the data | |
18 changes: 7 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@

<groupId>io.cdap.plugin</groupId>
<artifactId>snowflake-plugins</artifactId>
<version>1.1.0-SNAPSHOT</version>
<version>1.1.6-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Snowflake plugins</name>

<properties>
<surefire.redirectTestOutputToFile>true</surefire.redirectTestOutputToFile>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- version properties -->
<cdap.version>6.1.0-SNAPSHOT</cdap.version>
<hydrator.version>2.3.0-SNAPSHOT</hydrator.version>
<cdap.version>6.4.1</cdap.version>
<hydrator.version>2.6.1</hydrator.version>
<commons.csv.version>1.6</commons.csv.version>
<hadoop.version>2.8.0</hadoop.version>
<spark2.version>2.3.1</spark2.version>
Expand All @@ -47,17 +47,13 @@
<powermock.version>1.7.4</powermock.version>
<guice.version>4.0</guice.version>
<opencsv.version>2.4</opencsv.version>
<snowflake-jdbc.version>3.13.24</snowflake-jdbc.version>
<snowflake-jdbc.version>4.3.4</snowflake-jdbc.version>
</properties>

<repositories>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public</url>
</repository>
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<url>https://central.sonatype.com/repository/maven-snapshots</url>
</repository>
</repositories>

Expand Down Expand Up @@ -398,8 +394,8 @@
<version>1.1.0</version>
<configuration>
<cdapArtifacts>
<parent>system:cdap-data-pipeline[6.1.0-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
<parent>system:cdap-data-streams[6.1.0-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
<parent>system:cdap-data-pipeline[6.4.1-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
<parent>system:cdap-data-streams[6.4.1-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
</cdapArtifacts>
</configuration>
<executions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public boolean canConnect() {
&& !containsMacro(PROPERTY_PASSWORD) && !containsMacro(PROPERTY_WAREHOUSE)
&& !containsMacro(PROPERTY_ROLE) && !containsMacro(PROPERTY_CLIENT_ID)
&& !containsMacro(PROPERTY_CLIENT_SECRET) && !containsMacro(PROPERTY_REFRESH_TOKEN)
&& !containsMacro(PROPERTY_PRIVATE_KEY));
&& !containsMacro(PROPERTY_PRIVATE_KEY) && !containsMacro(PROPERTY_PASSPHRASE));
}

protected void validateConnection(FailureCollector collector) {
Expand All @@ -299,8 +299,8 @@ protected void validateConnection(FailureCollector collector) {
.withConfigProperty(PROPERTY_USERNAME);

// TODO: for oauth2
if (keyPairEnabled) {
failure.withConfigProperty(PROPERTY_PRIVATE_KEY);
if (Boolean.TRUE.equals(keyPairEnabled)) {
failure.withConfigProperty(PROPERTY_PRIVATE_KEY).withConfigProperty(PROPERTY_PASSPHRASE);
} else {
failure.withConfigProperty(PROPERTY_PASSWORD);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import io.cdap.plugin.snowflake.common.OAuthUtil;
import io.cdap.plugin.snowflake.common.exception.ConnectionTimeoutException;
import io.cdap.plugin.snowflake.common.util.QueryUtil;
import net.snowflake.client.jdbc.SnowflakeBasicDataSource;
import net.snowflake.client.internal.api.implementation.datasource.SnowflakeBasicDataSource;
import org.apache.http.impl.client.HttpClients;

import java.io.BufferedWriter;
Expand All @@ -32,6 +32,7 @@
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
Expand Down Expand Up @@ -66,6 +67,30 @@ public void runSQL(String query) throws IOException {

}

/**
* Returns field descriptors for specified table name
* @param schemaName The name of schema containing the table
* @param tableName The name of table whose metadata needs to be retrieved
* @return list of field descriptors
*/
public List<SnowflakeFieldDescriptor> getFieldDescriptors(String schemaName, String tableName) throws IOException {
List<SnowflakeFieldDescriptor> fieldDescriptors = new ArrayList<>();
try (Connection connection = dataSource.getConnection()) {
DatabaseMetaData dbMetaData = connection.getMetaData();
try (ResultSet columns = dbMetaData.getColumns(null, schemaName, tableName, null)) {
while (columns.next()) {
String columnName = columns.getString("COLUMN_NAME");
int columnType = columns.getInt("DATA_TYPE");
boolean nullable = columns.getInt("NULLABLE") == DatabaseMetaData.columnNullable;
fieldDescriptors.add(new SnowflakeFieldDescriptor(columnName, columnType, nullable));
}
}
} catch (SQLException e) {
throw new IOException();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The caught SQLException is swallowed, and a generic IOException is thrown without a message or the root cause. This makes troubleshooting database connection or query issues extremely difficult. Please pass the original exception as the cause to the IOException.

Suggested change
throw new IOException();
throw new IOException("Failed to retrieve field descriptors for table: " + tableName, e);

}
return fieldDescriptors;
}

/**
* Returns field descriptors for specified import query.
*
Expand Down Expand Up @@ -110,7 +135,11 @@ private void initDataSource(SnowflakeBasicDataSource dataSource, BaseSnowflakeCo

if (config.getOauth2Enabled()) {
String accessToken = OAuthUtil.getAccessTokenByRefreshToken(HttpClients.createDefault(), config);
dataSource.setOauthToken(accessToken);
// In JDBC 4.x, setOauthToken() was removed. The recommended approach is to explicitly
// set the authenticator to "oauth" and pass the access token as the password.
// Migration guide: https://docs.snowflake.com/en/developer-guide/jdbc/jdbc-migration
dataSource.setAuthenticator("oauth");
dataSource.setPassword(accessToken);
} else if (config.getKeyPairEnabled()) {
dataSource.setUser(config.getUsername());

Expand Down Expand Up @@ -171,4 +200,13 @@ private static String writeTextToTmpFile(String text) {
throw new RuntimeException("Cannot write key to temporary file", e);
}
}

/**
* Retrieves schema name from the configuration
*
* @return The schema name
*/
public String getSchema() {
return config.getSchemaName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,24 @@

package io.cdap.plugin.snowflake.common.util;

import com.google.common.base.Strings;

/**
* Transforms import query.
*/
public class QueryUtil {

// Matches "limit <number>". Also "limit $$$$" and "limit ''" which means unlimited in Snowflake.
private static final String LIMIT_PATTERN = "(?i)LIMIT (''|\\$\\$\\$\\$|\\d+)";
private static final String LIMIT_PATTERN = "(?i)LIMIT (NULL|''|\\$\\$\\$\\$|\\d+)";
private static final String LIMIT_STRING = "limit %s";

private QueryUtil() {
}

public static String removeSemicolon(String importQuery) {
if (Strings.isNullOrEmpty(importQuery)) {
return null;
}
if (importQuery.endsWith(";")) {
importQuery = importQuery.substring(0, importQuery.length() - 1);
}
Expand Down
Loading
Loading