diff --git a/sqlutil/printrows.go b/sqlutil/printrows.go new file mode 100644 index 00000000..fda8d466 --- /dev/null +++ b/sqlutil/printrows.go @@ -0,0 +1,53 @@ +package sqlutil + +import ( + "database/sql" + "fmt" + "io" + "text/tabwriter" +) + +// PrintRowsToTable prints the rows to the output in a table format. +func PrintRowsToTable(rows *sql.Rows, output io.Writer) error { + w := tabwriter.NewWriter(output, 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) + // Get column names + columns, err := rows.Columns() + if err != nil { + return fmt.Errorf("getting column names: %w", err) + } + + for _, column := range columns { + fmt.Fprint(w, "\t"+column) + } + fmt.Fprintln(w, "\t") + for range columns { + fmt.Fprint(w, "\t---") + } + fmt.Fprintln(w, "\t") + + values := make([]any, len(columns)) + scanArgs := make([]any, len(values)) + for i := range values { + scanArgs[i] = &values[i] + } + + for rows.Next() { + err = rows.Scan(scanArgs...) + if err != nil { + return fmt.Errorf("scanning row: %w", err) + } + for _, value := range values { + switch value := value.(type) { + case nil: + fmt.Fprint(w, "\tNULL") + case []byte: + fmt.Fprint(w, "\t"+string(value)) + default: + fmt.Fprintf(w, "\t%v", value) + } + } + fmt.Fprintln(w, "\t") + } + w.Flush() + return rows.Err() +} diff --git a/sqlutil/printrows_test.go b/sqlutil/printrows_test.go new file mode 100644 index 00000000..6b3afbe4 --- /dev/null +++ b/sqlutil/printrows_test.go @@ -0,0 +1,46 @@ +package sqlutil_test + +import ( + "bytes" + "fmt" + "testing" + + "github.com/ory/dockertest/v3" + "github.com/stretchr/testify/require" + + "github.com/rudderlabs/rudder-go-kit/sqlutil" + "github.com/rudderlabs/rudder-go-kit/testhelper/docker/resource" +) + +func TestPrintRowsToTable(t *testing.T) { + pool, err := dockertest.NewPool("") + require.NoError(t, err) + postgres, err := resource.SetupPostgres(pool, t) + require.NoError(t, err) + + _, err = postgres.DB.Exec(`CREATE TABLE users ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INT NOT NULL, + info JSONB + )`) + require.NoError(t, err) + _, err = postgres.DB.Exec(`INSERT INTO users (name, age, info) VALUES ('John Doe', 20, '{"email": "jdoe@example.com"}')`) + require.NoError(t, err) + _, err = postgres.DB.Exec(`INSERT INTO users (name, age, info) VALUES ('Eva Chung', 20, '{"email": "echung@example.com"}')`) + require.NoError(t, err) + + var out bytes.Buffer + rows, err := postgres.DB.Query(`SELECT * FROM users`) + require.NoError(t, err) + defer func() { _ = rows.Close() }() + err = sqlutil.PrintRowsToTable(rows, &out) + require.NoError(t, err) + fmt.Println(out.String()) + require.Equal(t, + ` | id| name| age| info| + | ---| ---| ---| ---| + | 1| John Doe| 20| {"email": "jdoe@example.com"}| + | 2| Eva Chung| 20| {"email": "echung@example.com"}| +`, out.String()) +}