[codex] Add NetSuite SuiteAnalytics ODBC source#675
Open
karakanb wants to merge 5 commits into
Open
Conversation
573c2f2 to
761ffd2
Compare
761ffd2 to
9a013b2
Compare
Contributor
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
pkg/source/netsuite/netsuite.go:469-487
**`uniqueColumnNames` can produce duplicate output names.** When a renamed duplicate (e.g., the second `name` becomes `name_2`) collides with an already-processed column also called `name_2`, both end up with the same name. Arrow schema construction downstream will then receive two columns with identical names, which can panic or produce a malformed record batch.
Concrete case: input columns `["name_2", "name", "name"]` → `seen["name_2"]=1` after the first iteration; the third iteration renames the second `name` to `name_2` without checking `seen`, yielding `["name_2", "name", "name_2"]`.
```suggestion
func uniqueColumnNames(columns []string) []string {
seen := make(map[string]int, len(columns))
names := make([]string, len(columns))
for i, column := range columns {
name := strings.TrimSpace(column)
if name == "" {
name = fmt.Sprintf("column_%d", i+1)
}
key := strings.ToLower(name)
count := seen[key]
seen[key] = count + 1
if count > 0 {
candidate := fmt.Sprintf("%s_%d", name, count+1)
for seen[strings.ToLower(candidate)] > 0 {
count++
candidate = fmt.Sprintf("%s_%d", name, count+1)
}
seen[strings.ToLower(candidate)]++
name = candidate
}
names[i] = name
}
return names
}
```
### Issue 2 of 2
pkg/source/netsuite/netsuite.go:422-440
`opts.Limit` is only enforced client-side in `streamRows`, but the SQL sent to NetSuite never includes a `LIMIT` clause. For large SuiteAnalytics tables this fetches the full result set over ODBC and discards rows after the fact, which can be very slow and memory-intensive.
```suggestion
func buildSuiteAnalyticsQuery(tableName string, opts source.ReadOptions) string {
query := fmt.Sprintf("SELECT * FROM %s", strings.TrimSpace(tableName))
var conditions []string
if opts.IncrementalKey != "" {
if opts.IntervalStart != nil {
conditions = append(conditions, fmt.Sprintf("%s >= %s", opts.IncrementalKey, suiteAnalyticsTimestampLiteral(*opts.IntervalStart)))
}
if opts.IntervalEnd != nil {
conditions = append(conditions, fmt.Sprintf("%s < %s", opts.IncrementalKey, suiteAnalyticsTimestampLiteral(*opts.IntervalEnd)))
}
}
if len(conditions) > 0 {
query += " WHERE " + strings.Join(conditions, " AND ")
query += " ORDER BY " + opts.IncrementalKey + " ASC"
}
if opts.Limit > 0 {
query += fmt.Sprintf(" FETCH FIRST %d ROWS ONLY", opts.Limit)
}
return query
}
```
Reviews (1): Last reviewed commit: "add netsuite suiteanalytics odbc connect..." | Re-trigger Greptile |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a NetSuite source backed by SuiteAnalytics Connect over ODBC, matching the SQL interface used by Fivetran-style NetSuite SuiteAnalytics extraction. Customers provide their own NetSuite ODBC driver/DSN or pass a full ODBC connection string; ingestr can also build a DSN-less string from driver, account, role, and credentials. The source streams SQL results into ingestr batches with schema inference, custom query: support, limits, and interval filters, and the Docker/CI setup now includes unixODBC for Linux builds. Validated with go test ./pkg/source/netsuite, make lint-ci, make licenses-check, and a Linux container smoke test using unixodbc-dev.