Skip to content

Commit

Permalink
🎉 New Source: SingleStore (#37337)
Browse files Browse the repository at this point in the history
Co-authored-by: Marcos Marx <marcosmarxm@users.noreply.github.com>
Co-authored-by: marcosmarxm <marcosmarxm@gmail.com>
  • Loading branch information
3 people authored Jun 6, 2024
1 parent a068aad commit 76573f0
Show file tree
Hide file tree
Showing 35 changed files with 3,489 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ enum class DatabaseDriver(val driverClassName: String, val urlFormatString: Stri
SNOWFLAKE("net.snowflake.client.jdbc.SnowflakeDriver", "jdbc:snowflake://%s/"),
YUGABYTEDB("com.yugabyte.Driver", "jdbc:yugabytedb://%s:%d/%s"),
EXASOL("com.exasol.jdbc.EXADriver", "jdbc:exa:%s:%d"),
TERADATA("com.teradata.jdbc.TeraDriver", "jdbc:teradata://%s/");
TERADATA("com.teradata.jdbc.TeraDriver", "jdbc:teradata://%s/"),
SINGLESTORE("com.singlestore.jdbc.Driver", "jdbc:singlestore://%s:%d/%s");

companion object {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ protected constructor(@JvmField protected val driverClassName: String) : BaseCon
ChronoUnit.SECONDS
)
.or { Optional.of<Duration>(POSTGRES_CONNECT_TIMEOUT_DEFAULT_DURATION) }
DatabaseDriver.MYSQL ->
DatabaseDriver.MYSQL,
DatabaseDriver.SINGLESTORE ->
maybeParseDuration(
connectionProperties["connectTimeout"],
ChronoUnit.MILLIS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ abstract class JdbcSourceAcceptanceTest<S : Source, T : TestDatabase<*, T, *>> {
// for them.
when (testdb.databaseDriver) {
DatabaseDriver.MYSQL,
DatabaseDriver.SINGLESTORE,
DatabaseDriver.CLICKHOUSE,
DatabaseDriver.TERADATA -> return
else -> {}
Expand Down Expand Up @@ -1211,6 +1212,7 @@ abstract class JdbcSourceAcceptanceTest<S : Source, T : TestDatabase<*, T, *>> {
// some databases don't make insertion order guarantee when equal ordering value
if (
testdb.databaseDriver == DatabaseDriver.TERADATA ||
testdb.databaseDriver == DatabaseDriver.SINGLESTORE ||
testdb.databaseDriver == DatabaseDriver.ORACLE
) {
MatcherAssert.assertThat(
Expand Down Expand Up @@ -1311,7 +1313,10 @@ abstract class JdbcSourceAcceptanceTest<S : Source, T : TestDatabase<*, T, *>> {
.map { r: AirbyteMessage -> r.record.data[COL_NAME].asText() }

// teradata doesn't make insertion order guarantee when equal ordering value
if (testdb.databaseDriver == DatabaseDriver.TERADATA) {
if (
testdb.databaseDriver == DatabaseDriver.TERADATA ||
testdb.databaseDriver == DatabaseDriver.SINGLESTORE
) {
MatcherAssert.assertThat(
listOf("c", "d", "e", "f"),
Matchers.containsInAnyOrder<Any>(*thirdSyncExpectedNames.toTypedArray()),
Expand Down Expand Up @@ -1706,6 +1711,7 @@ abstract class JdbcSourceAcceptanceTest<S : Source, T : TestDatabase<*, T, *>> {
get() =
when (testdb.databaseDriver) {
DatabaseDriver.MYSQL,
DatabaseDriver.SINGLESTORE,
DatabaseDriver.CLICKHOUSE,
DatabaseDriver.TERADATA -> testdb.databaseName
else -> SCHEMA_NAME
Expand Down
71 changes: 71 additions & 0 deletions airbyte-integrations/connectors/source-singlestore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Source SingleStore

This is the repository for the Singlestore source connector in Java.
For information about how to use this connector within Airbyte, see [the User Documentation](https://docs.airbyte.com/integrations/sources/singlestore).

## Local development

#### Building via Gradle
From the Airbyte repository root, run:
```
./gradlew :airbyte-integrations:connectors:source-singlestore:build
```

#### Create credentials
**If you are a community contributor**, generate the necessary credentials and place them in `secrets/config.json` conforming to the spec file in `src/main/resources/spec.json`.
Note that the `secrets` directory is git-ignored by default, so there is no danger of accidentally checking in sensitive information.

**If you are an Airbyte core member**, follow the [instructions](https://docs.airbyte.com/connector-development#using-credentials-in-ci) to set up the credentials.

### Locally running the connector docker image

#### Build
Build the connector image via Gradle:
```
./gradlew :airbyte-integrations:connectors:source-singlestore:buildConnectorImage
```

Once built, the docker image name and tag will be `airbyte/source-singlestore:dev`.

#### Run
Then run any of the connector commands as follows:
```
docker run --rm airbyte/source-singlestore:dev spec
docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-singlestore:dev check --config /secrets/config.json
docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-singlestore:dev discover --config /secrets/config.json
docker run --rm -v $(pwd)/secrets:/secrets -v $(pwd)/integration_tests:/integration_tests airbyte/source-singlestore:dev read --config /secrets/config.json --catalog /integration_tests/configured_catalog.json
```

## Testing
We use `JUnit` for Java tests.

### Unit and Integration Tests
Place unit tests under `src/test/...`
Place integration tests in `src/test-integration/...`

#### Acceptance Tests
Airbyte has a standard test suite that all source connectors must pass. Implement the `TODO`s in
`src/test-integration/java/io/airbyte/integrations/sources/singlestoreSourceAcceptanceTest.java`.

### Using gradle to run tests
All commands should be run from airbyte project root.
To run unit tests:
```
./gradlew :airbyte-integrations:connectors:source-singlestore:unitTest
```
To run acceptance and custom integration tests:
```
./gradlew :airbyte-integrations:connectors:source-singlestore:integrationTest
```

## Dependency Management

### Publishing a new version of the connector
You've checked out the repo, implemented a million dollar feature, and you're ready to share your changes with the world. Now what?
1. Make sure your changes are passing our test suite: `airbyte-ci connectors --name=source-singlestore test`
2. Bump the connector version in `metadata.yaml`: increment the `dockerImageTag` value. Please follow [semantic versioning for connectors](https://docs.airbyte.com/contributing-to-airbyte/resources/pull-requests-handbook/#semantic-versioning-for-connectors).
3. Make sure the `metadata.yaml` content is up to date.
4. Make the connector documentation and its changelog are up to date (`docs/integrations/sources/singlestore.md`).
5. Create a Pull Request: use [our PR naming conventions](https://docs.airbyte.com/contributing-to-airbyte/resources/pull-requests-handbook/#pull-request-title-convention).
6. Pat yourself on the back for being an awesome contributor.
7. Someone from Airbyte will take a look at your PR and iterate with you to merge it into master.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# See [Connector Acceptance Tests](https://docs.airbyte.com/connector-development/testing-connectors/connector-acceptance-tests-reference)
# for more information about how to configure these tests
connector_image: airbyte/source-singlestore:dev
acceptance_tests:
spec:
tests:
- spec_path: "src/test-integration/resources/expected_spec.json"
config_path: "src/test-integration/resources/dummy_config.json"
50 changes: 50 additions & 0 deletions airbyte-integrations/connectors/source-singlestore/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import org.jsonschema2pojo.SourceType

plugins {
id 'application'
id 'airbyte-java-connector'
id 'org.jsonschema2pojo' version '1.2.1'
}

tasks.named('sourcesJar').configure {
dependsOn tasks.matching { it.name == 'generateJsonSchema2Pojo' }
}

airbyteJavaConnector {
cdkVersionRequired = '0.30.1'
features = ['db-sources']
useLocalCdk = true
}

java {
compileJava {
options.compilerArgs += "-Xlint:-try,-rawtypes"
}
}

airbyteJavaConnector.addCdkDependencies()

application {
mainClass = 'io.airbyte.integrations.source.singlestore.SingleStoreSource'
}

dependencies {
implementation 'com.singlestore:singlestore-jdbc-client:1.2.2'
testImplementation 'org.apache.commons:commons-lang3:3.11'
testFixturesImplementation 'org.testcontainers:jdbc:1.19.0'
integrationTestJavaImplementation project(':airbyte-integrations:connectors:source-singlestore')
}

jsonSchema2Pojo {
sourceType = SourceType.YAMLSCHEMA
source = files("${sourceSets.main.output.resourcesDir}/internal_models")
targetDirectory = new File(project.buildDir, 'generated/src/gen/java/')
removeOldOutput = true

targetPackage = 'io.airbyte.integrations.source.singlestore.internal.models'

useLongIntegers = true
generateBuilders = true
includeConstructors = false
includeSetters = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
testExecutionConcurrency=1

JunitMethodExecutionTimeout=5 m
28 changes: 28 additions & 0 deletions airbyte-integrations/connectors/source-singlestore/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
#


import pytest

pytest_plugins = ("connector_acceptance_test.plugin",)


@pytest.fixture(scope="session", autouse=True)
def connector_setup():
"""This fixture is a placeholder for external resources that acceptance test might require."""
yield
25 changes: 25 additions & 0 deletions airbyte-integrations/connectors/source-singlestore/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
data:
allowedHosts:
hosts:
- ${host}
registries:
oss:
enabled: true
cloud:
enabled: false
connectorSubtype: database
connectorType: source
definitionId: 2e8ae725-0069-4452-afa0-d1848cf69676
dockerImageTag: 0.1.0
dockerRepository: airbyte/source-singlestore
githubIssueLabel: source-singlestore
icon: singlestore.svg
license: MIT
name: SingleStore
releaseDate:
supportLevel: community
releaseStage: alpha
documentationUrl: https://docs.airbyte.com/integrations/sources/singlestore
tags:
- language:java
metadataSpecVersion: "1.0"
Loading

0 comments on commit 76573f0

Please sign in to comment.