Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 32 additions & 0 deletions docker-compose-hanaexpress-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
services:
# HANA Express Database for testing
hanaexpress:
image: saplabs/hanaexpress:latest
container_name: baton-hanaexpress-test
hostname: hanaexpress
ulimits:
nofile:
soft: 1048576
hard: 1048576
sysctls:
kernel.shmmax: 1073741824
net.ipv4.ip_local_port_range: 40000 60999
kernel.shmall: 8388608
ports:
- "39013:39013"
- "39017:39017"
- "39041:39041"
- "39042:39042"
- "39043:39043"
- "39044:39044"
- "39045:39045"
- "1128:1128"
- "1129:1129"
- "59013:59013"
- "59014:59014"
command: >
--passwords-url file:///hana/mounts/password.json
--agree-to-sap-license

volumes:
- ./test/hanaexpress:/hana/mounts
51 changes: 51 additions & 0 deletions examples/sap-hana-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
app_name: HANA Express Test

connect:
dsn: "hdb://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}"

resource_types:
user:
name: "User"
description: "A user within the SAP HANA system"
list:
query: |
SELECT
USER_ID,
USER_NAME,
CASE
WHEN USER_DEACTIVATED = 'TRUE' THEN 'inactive'
ELSE 'active'
END as STATUS,
CREATE_TIME,
LAST_SUCCESSFUL_CONNECT,
COMMENTS
FROM
"SYS"."USERS"
ORDER BY USER_ID
LIMIT ?<Limit> OFFSET ?<Offset>
# Pagination configuration
pagination:
strategy: "offset"
primary_key: "USER_ID"
# Mapping of query results to resource fields
map:
id: ".USER_ID"
display_name: ".USER_NAME"
description: ".USER_NAME"
# Extra attributes (traits) for the user resource
traits:
user:
status: .STATUS
login: .USER_NAME
# Email addresses
# emails:
# - ".email"
# account_type: ".account_type"
last_login: .LAST_SUCCESSFUL_CONNECT
created_at: .CREATE_TIME
profile:
comments: .COMMENTS
user_id: .USER_ID
created_at: .CREATE_TIME
last_login: .LAST_SUCCESSFUL_CONNECT
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/conductorone/baton-sql
go 1.25

require (
github.com/SAP/go-hdb v1.14.5
github.com/conductorone/baton-sdk v0.4.6
github.com/elliotchance/phpserialize v1.4.0
github.com/ennyjfrick/ruleguard-logfatal v0.0.2
Expand All @@ -16,7 +17,7 @@ require (
github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.11.1
go.uber.org/zap v1.27.0
golang.org/x/text v0.24.0
golang.org/x/text v0.29.0
google.golang.org/grpc v1.71.1
google.golang.org/protobuf v1.36.6
gopkg.in/yaml.v3 v3.0.1
Expand Down Expand Up @@ -125,7 +126,7 @@ require (
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/oauth2 v0.29.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/term v0.31.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect
Expand Down
18 changes: 10 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/SAP/go-hdb v1.14.5 h1:SJcaEyMw4t6UPasxNTAZENXMguK2HKorpwiY5KnnAZk=
github.com/SAP/go-hdb v1.14.5/go.mod h1:n2822T2EW6WVy7+M6p+YrDe9qG/U/lY5RCeQzd+YwWA=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/aws/aws-lambda-go v1.48.0 h1:1aZUYsrJu0yo5fC4z+Rba1KhNImXcJcvHu763BxoyIo=
Expand Down Expand Up @@ -355,8 +357,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand All @@ -375,8 +377,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -393,8 +395,8 @@ golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
Expand All @@ -404,8 +406,8 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
5 changes: 4 additions & 1 deletion pkg/connector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ func (c *Connector) Metadata(ctx context.Context) (*v2.ConnectorMetadata, error)
// Validate is called to ensure that the connector is properly configured. It should exercise any API credentials
// to be sure that they are valid.
func (c *Connector) Validate(ctx context.Context) (annotations.Annotations, error) {
// TODO: Validate SQL connection.
err := c.db.PingContext(ctx)
if err != nil {
Comment thread
pquerna marked this conversation as resolved.
return nil, err
}
return nil, nil
}

Expand Down
10 changes: 10 additions & 0 deletions pkg/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"regexp"

"github.com/conductorone/baton-sql/pkg/database/hdb"
"github.com/conductorone/baton-sql/pkg/database/mysql"
"github.com/conductorone/baton-sql/pkg/database/oracle"
"github.com/conductorone/baton-sql/pkg/database/postgres"
Expand All @@ -26,6 +27,7 @@ const (
SQLite
MSSQL
Oracle
HDB
)

func updateFromEnv(dsn string) (string, error) {
Expand Down Expand Up @@ -105,6 +107,14 @@ func Connect(ctx context.Context, dsn string, user string, password string) (*sq
return nil, Unknown, err
}
return db, PostgreSQL, nil

case "hdb":
db, err := hdb.Connect(ctx, parsedDsn.String())
if err != nil {
return nil, Unknown, err
}
return db, HDB, nil

default:
return nil, Unknown, fmt.Errorf("unsupported database scheme: %s", parsedDsn.Scheme)
}
Expand Down
17 changes: 17 additions & 0 deletions pkg/database/hdb/hdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package hdb

import (
"context"
"database/sql"

_ "github.com/SAP/go-hdb/driver"
)

func Connect(ctx context.Context, dsn string) (*sql.DB, error) {
db, err := sql.Open("hdb", dsn)
if err != nil {
return nil, err
}

return db, nil
}
Comment on lines +10 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add documentation for the exported function.

The exported Connect function is missing a documentation comment. Per coding guidelines, all exported items must have complete sentence comments ending with periods.

Apply this diff to add documentation:

+// Connect establishes a connection to a SAP HANA database using the provided DSN.
+// It returns a configured sql.DB instance or an error if the connection cannot be opened.
 func Connect(ctx context.Context, dsn string) (*sql.DB, error) {
 	db, err := sql.Open("hdb", dsn)
 	if err != nil {
 		return nil, err
 	}
 
 	return db, nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func Connect(ctx context.Context, dsn string) (*sql.DB, error) {
db, err := sql.Open("hdb", dsn)
if err != nil {
return nil, err
}
return db, nil
}
// Connect establishes a connection to a SAP HANA database using the provided DSN.
// It returns a configured sql.DB instance or an error if the connection cannot be opened.
func Connect(ctx context.Context, dsn string) (*sql.DB, error) {
db, err := sql.Open("hdb", dsn)
if err != nil {
return nil, err
}
return db, nil
}
🤖 Prompt for AI Agents
In pkg/database/hdb/hdb.go around lines 10 to 17, the exported Connect function
lacks a documentation comment; add a complete sentence comment immediately above
the function that describes what Connect does, mentions the ctx and dsn
parameters (context for cancellation/timeout and Data Source Name), and
summarizes the return values (a *sql.DB on success or an error on failure), and
ensure the sentence ends with a period.

11 changes: 0 additions & 11 deletions pkg/database/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,10 @@ import (
"fmt"
"net/url"
"strings"
"time"

_ "github.com/go-sql-driver/mysql"
)

const (
MaxIdleConns = 10
MaxOpenConns = 10
MaxConnLifetime = 5 * time.Minute
)

func convertURItoDSN(uri string) (string, error) {
parsedURI, err := url.Parse(uri)
if err != nil {
Expand Down Expand Up @@ -62,9 +55,5 @@ func Connect(ctx context.Context, dsn string) (*sql.DB, error) {
return nil, err
}

db.SetMaxOpenConns(MaxOpenConns)
db.SetMaxIdleConns(MaxIdleConns)
db.SetConnMaxLifetime(MaxConnLifetime)

return db, nil
}
3 changes: 3 additions & 0 deletions test/hanaexpress/password.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"master_password" : "HXEHana1"
}
Loading