Skip to content

[codex] Add NetSuite SuiteAnalytics ODBC source#675

Open
karakanb wants to merge 5 commits into
mainfrom
netsuite-connector-client
Open

[codex] Add NetSuite SuiteAnalytics ODBC source#675
karakanb wants to merge 5 commits into
mainfrom
netsuite-connector-client

Conversation

@karakanb
Copy link
Copy Markdown
Contributor

@karakanb karakanb commented Jun 1, 2026

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.

@karakanb karakanb force-pushed the netsuite-connector-client branch from 573c2f2 to 761ffd2 Compare June 1, 2026 18:06
@karakanb karakanb changed the title [codex] Add NetSuite source connector [codex] Add NetSuite SuiteAnalytics source Jun 1, 2026
@karakanb karakanb force-pushed the netsuite-connector-client branch from 761ffd2 to 9a013b2 Compare June 1, 2026 18:47
@karakanb karakanb changed the title [codex] Add NetSuite SuiteAnalytics source [codex] Add NetSuite SuiteAnalytics ODBC source Jun 1, 2026
@karakanb karakanb marked this pull request as ready for review June 1, 2026 18:51
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 1, 2026

Prompt To Fix All With AI
Fix 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

Comment thread pkg/source/netsuite/netsuite.go
Comment thread pkg/source/netsuite/netsuite.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant