Skip to content

Commit

Permalink
string and number pushdown
Browse files Browse the repository at this point in the history
  • Loading branch information
judell committed Sep 23, 2023
1 parent 9fbf99d commit f66919e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 16 deletions.
54 changes: 38 additions & 16 deletions odbc/table_code_odbc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ func getSchemas(ctx context.Context, dataSource string, tablename string) ([]*pl
}
defer db.Close()

rows, err := db.Query(fmt.Sprintf("SELECT * FROM %s WHERE 1=0", tablename))
// Fetch a single row to probe types
rows, err := db.Query(fmt.Sprintf("SELECT * FROM %s LIMIT 1", tablename))
if err != nil {
return nil, err
}
Expand All @@ -34,15 +35,43 @@ func getSchemas(ctx context.Context, dataSource string, tablename string) ([]*pl
if err != nil {
return nil, err
}
plugin.Logger(ctx).Debug("odbc.getSchema", "columnNames", columnNames)

if !rows.Next() {
// Handle the case where there are no rows
return nil, fmt.Errorf("unable to retrieve column data for table %s", tablename)
}

// Use sql.RawBytes to avoid actual type parsing for now
values := make([]interface{}, len(columnNames))
valuePtrs := make([]interface{}, len(columnNames))
for i := 0; i < len(columnNames); i++ {
valuePtrs[i] = &values[i]
}

// Scan values from the row into the slice
if err := rows.Scan(valuePtrs...); err != nil {
return nil, err
}

cols := make([]*plugin.Column, len(columnNames))
for i, columnName := range columnNames {
for i, colName := range columnNames {
var columnType proto.ColumnType
switch values[i].(type) {
case int, int32, int64:
columnType = proto.ColumnType_INT
case float32, float64:
columnType = proto.ColumnType_DOUBLE
case string:
columnType = proto.ColumnType_STRING
// Add more type mappings as needed
default:
columnType = proto.ColumnType_STRING
}
cols[i] = &plugin.Column{
Name: columnName,
Type: proto.ColumnType_STRING,
Description: dataSource + " " + columnName,
Transform: transform.FromField(helpers.EscapePropertyName(columnName)),
Name: colName,
Type: columnType,
Description: dataSource + " " + colName,
Transform: transform.FromField(helpers.EscapePropertyName(colName)),
}
}

Expand Down Expand Up @@ -123,24 +152,17 @@ func fetchFromDatabase(ctx context.Context, dsn string, tablename string, quals

query := "SELECT * FROM " + tablename

// Construct the WHERE clause
// Construct the WHERE clause using protoToODBCValue
conds := make([]string, 0)
for _, qualsForCol := range quals {
for _, qual := range qualsForCol.Quals {
if qual.Value.Value == nil {
conds = append(conds, fmt.Sprintf("%s %s", qual.Column, qual.Operator))
} else {
var valueStr string

strVal := qual.Value.GetStringValue()
if strVal != "" {
valueStr = fmt.Sprintf("'%s'", strVal)
}

valueStr := protoToODBCValue(qual.Value)
conds = append(conds, fmt.Sprintf("%s %s %s", qual.Column, qual.Operator, valueStr))
}
}

}
if len(conds) > 0 {
query = query + " WHERE " + strings.Join(conds, " AND ")
Expand Down
24 changes: 24 additions & 0 deletions odbc/utils.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package odbc

import (
"fmt"
"strings"

"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
)

func splitDataSourceAndTable(s string) (string, string) {
Expand All @@ -11,3 +14,24 @@ func splitDataSourceAndTable(s string) (string, string) {
}
return parts[0], parts[1]
}

func protoToODBCValue(val *proto.QualValue) string {
switch val.GetValue().(type) {
case *proto.QualValue_BoolValue:
if val.GetBoolValue() {
return "TRUE"
}
return "FALSE"
case *proto.QualValue_DoubleValue:
return fmt.Sprintf("%f", val.GetDoubleValue())
case *proto.QualValue_Int64Value:
return fmt.Sprintf("%d", val.GetInt64Value())
case *proto.QualValue_StringValue:
return fmt.Sprintf("'%s'", val.GetStringValue())
// Add cases for other data types as needed.
// Note: For types like CIDR or Timestamp which may not be universally supported
// across all databases behind ODBC, you might need more nuanced handling.
default:
return "<INVALID>" // this will probably cause an error on the query, which might be acceptable
}
}

0 comments on commit f66919e

Please sign in to comment.