Skip to content

Commit

Permalink
Merge pull request #78 from stewartbryson/stewart
Browse files Browse the repository at this point in the history
Support for partial connection properties.
  • Loading branch information
stewartbryson authored Mar 24, 2023
2 parents abc23d9 + c1a792a commit b812683
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.github.stewartbryson
import groovy.util.logging.Slf4j
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.options.Option

Expand Down Expand Up @@ -37,16 +38,47 @@ abstract class SnowflakeEphemeralTask extends SnowflakeTask {
@Option(option = "ephemeral-name", description = "Optional: specify the ephemeral database name instead of relying on an autogenerated value.")
String ephemeralName = extension.ephemeralName

/**
* The connection database in case it wasn't in the connection.
*/
@Internal
String connectionDatabase

/**
* The connection schema in case it wasn't in the connection.
*/
@Internal
String connectionSchema

/**
* The connection role in case it wasn't in the connection.
*/
@Internal
String connectionRole

/**
* Create an ephemeral Snowflake clone and return a session to it.
*
* @return a session to the ephemeral Snowflake clone.
*/
def createClone() {
if (useEphemeral) {
session.jdbcConnection().createStatement().execute("create database if not exists ${ephemeralName} clone $database")
session.jdbcConnection().createStatement().execute("grant ownership on database ${ephemeralName} to $role")
session.jdbcConnection().createStatement().execute("use schema ${ephemeralName}.${schema}")
// record connection attributes
try {
connectionDatabase = getSingleValue('SELECT CURRENT_DATABASE()')
connectionSchema = getSingleValue('SELECT CURRENT_SCHEMA()')
connectionRole = getSingleValue('SELECT CURRENT_ROLE()')
log.debug "Connection database, schema, role: $connectionDatabase, $connectionSchema, $connectionRole"
} catch (Exception e) {
throw new Exception("Connection context is not available.", e)
}
try {
session.jdbcConnection().createStatement().execute("create database if not exists ${ephemeralName} clone ${connectionDatabase}")
session.jdbcConnection().createStatement().execute("grant ownership on database ${ephemeralName} to ${connectionRole}")
session.jdbcConnection().createStatement().execute("use schema ${ephemeralName}.${connectionSchema}")
} catch (Exception e) {
throw new Exception("Cloning ephemeral clone failed.", e)
}
log.warn "Ephemeral clone $ephemeralName created."
}
}
Expand All @@ -57,8 +89,12 @@ abstract class SnowflakeEphemeralTask extends SnowflakeTask {
def dropClone() {
if (useEphemeral && !keepEphemeral) {
// drop the ephemeral database
session.jdbcConnection().createStatement().execute("drop database if exists ${ephemeralName}")
session.jdbcConnection().createStatement().execute("use schema ${database}.${schema}")
try {
session.jdbcConnection().createStatement().execute("drop database if exists ${ephemeralName}")
session.jdbcConnection().createStatement().execute("use schema ${connectionDatabase}.${connectionSchema}")
} catch (Exception e) {
throw new Exception("Dropping ephemeral clone failed.", e)
}
log.warn "Ephemeral clone $ephemeralName dropped."
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@ class SnowflakeExtension {
*/
String database
/**
* The Snowflake schema to connect with. Default: 'public'.
* The Snowflake schema to connect with.
*/
String schema = 'public'
String schema
/**
* The Snowflake role to connect with.
*/
String role
/**
* The Snowflake warehouse to connect with. Default: 'compute_wh'.
* The Snowflake warehouse to connect with.
*/
String warehouse = "compute_wh"
String warehouse
/**
* The Snowflake stage to upload to. Default: 'maven'.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ abstract class SnowflakeJvm extends SnowflakeEphemeralTask {
}
} else if (extension.publishUrl) {
// ensure that the stage and the publishUrl are aligned
String selectStage = getColumnValue("select stage_url from information_schema.stages where stage_name=upper('$stage') and stage_schema=upper('$schema') and stage_type='External Named'")
String selectStage = getSingleValue("select stage_url from information_schema.stages where stage_name=upper('$stage') and stage_schema=upper('$schema') and stage_type='External Named'")
assert selectStage == extension.publishUrl
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ abstract class SnowflakeTask extends DefaultTask {
}

/**
* The Snowflake account URL, for instance: https://gradle-snowflake.us-east-1.snowflakecomputing.com:443. Overrides {@link SnowflakeExtension#account}.
* The Snowflake account URL, for instance: https://gradle-snowflake.us-east-1.snowflakecomputing.com. Overrides {@link SnowflakeExtension#account}.
*/
@Optional
@Input
Expand Down Expand Up @@ -103,14 +103,24 @@ abstract class SnowflakeTask extends DefaultTask {
*/
Session createSession() {
Map props = [
url : account,
user : user,
password : password,
role : role,
warehouse: warehouse,
db : database,
schema : schema
url : account,
user : user,
password: password
]
// add the optional connection parameters
if (role != 'null') {
props.role = role
}
if (warehouse != 'null') {
props.warehouse = warehouse
}
if (database != 'null') {
props.db = database
}
if (schema != 'null') {
props.schema = schema
}

Map printable = props.clone()
printable.password = "*********"
log.info "Snowflake config: $printable"
Expand All @@ -136,7 +146,7 @@ abstract class SnowflakeTask extends DefaultTask {
*
* @return a scalar column value.
*/
def getColumnValue(String sql) {
def getSingleValue(String sql) {
Statement statement = session.jdbcConnection().createStatement()
ResultSet rs = statement.executeQuery(sql)
def columnValue
Expand Down
2 changes: 1 addition & 1 deletion src/markdown/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
```
The `functionalTest` task contains all the tests that actually make a connection to Snowflake and test a deployment.
> WARNING: Ensure that the credential you provide below are for a safe development database.
> WARNING: Ensure that the credential provided below are for a safe development database.
To run `functionalTest`, create the following entries in `~/.gradle/gradle.properties`:
```properties
Expand Down

0 comments on commit b812683

Please sign in to comment.