mirror of
https://github.com/turbot/steampipe.git
synced 2025-12-19 18:12:43 -05:00
- JSON output format has changed to move the rows to under a `rows` property, with timing information under the `metadata` property - Update timing display to show rows returned and rows fetched, as well as adding verbose mode which lists all scans - Use enums for output mode and timing mode - timing is now either `on`, `off` or `verbose` - Bugfix: ensure error is returned from ExecuteSystemClientCall. Closes #4246
105 lines
3.5 KiB
Go
105 lines
3.5 KiB
Go
package queryresult
|
|
|
|
import (
|
|
"github.com/turbot/steampipe-plugin-sdk/v5/grpc"
|
|
"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
|
|
"time"
|
|
)
|
|
|
|
type ScanMetadataRow struct {
|
|
// the fields of this struct need to be public since these are populated by pgx using RowsToStruct
|
|
Connection string `db:"connection,optional" json:"connection"`
|
|
Table string `db:"table" json:"table"`
|
|
CacheHit bool `db:"cache_hit" json:"cache_hit"`
|
|
RowsFetched int64 `db:"rows_fetched" json:"rows_fetched"`
|
|
HydrateCalls int64 `db:"hydrate_calls" json:"hydrate_calls"`
|
|
StartTime time.Time `db:"start_time" json:"start_time"`
|
|
DurationMs int64 `db:"duration_ms" json:"duration_ms"`
|
|
Columns []string `db:"columns" json:"columns"`
|
|
Limit *int64 `db:"limit" json:"limit,omitempty"`
|
|
Quals []grpc.SerializableQual `db:"quals" json:"quals,omitempty"`
|
|
}
|
|
|
|
func NewScanMetadataRow(connection string, table string, columns []string, quals map[string]*proto.Quals, startTime time.Time, diration time.Duration, limit int64, m *proto.QueryMetadata) ScanMetadataRow {
|
|
res := ScanMetadataRow{
|
|
Connection: connection,
|
|
Table: table,
|
|
StartTime: startTime,
|
|
DurationMs: diration.Milliseconds(),
|
|
Columns: columns,
|
|
Quals: grpc.QualMapToSerializableSlice(quals),
|
|
}
|
|
if limit == -1 {
|
|
res.Limit = nil
|
|
} else {
|
|
res.Limit = &limit
|
|
}
|
|
if m != nil {
|
|
res.CacheHit = m.CacheHit
|
|
res.RowsFetched = m.RowsFetched
|
|
res.HydrateCalls = m.HydrateCalls
|
|
}
|
|
return res
|
|
}
|
|
|
|
// AsResultRow returns the ScanMetadata as a map[string]interface which can be returned as a query result
|
|
func (m ScanMetadataRow) AsResultRow() map[string]any {
|
|
res := map[string]any{
|
|
"connection": m.Connection,
|
|
"table": m.Table,
|
|
"cache_hit": m.CacheHit,
|
|
"rows_fetched": m.RowsFetched,
|
|
"hydrate_calls": m.HydrateCalls,
|
|
"start_time": m.StartTime,
|
|
"duration_ms": m.DurationMs,
|
|
"columns": m.Columns,
|
|
"quals": m.Quals,
|
|
}
|
|
// explicitly set limit to nil if needed (otherwise postgres returns `1`)
|
|
if m.Limit != nil {
|
|
res["limit"] = *m.Limit
|
|
} else {
|
|
res["limit"] = nil // Explicitly set nil
|
|
}
|
|
return res
|
|
}
|
|
|
|
type QueryRowSummary struct {
|
|
UncachedRowsFetched int64 `db:"uncached_rows_fetched" json:"uncached_rows_fetched"`
|
|
CachedRowsFetched int64 `db:"cached_rows_fetched" json:"cached_rows_fetched"`
|
|
HydrateCalls int64 `db:"hydrate_calls" json:"hydrate_calls"`
|
|
ScanCount int64 `db:"scan_count" json:"scan_count"`
|
|
ConnectionCount int64 `db:"connection_count" json:"connection_count"`
|
|
// map connections to the scans
|
|
connections map[string]struct{}
|
|
}
|
|
|
|
func NewQueryRowSummary() *QueryRowSummary {
|
|
return &QueryRowSummary{
|
|
connections: make(map[string]struct{}),
|
|
}
|
|
}
|
|
func (s *QueryRowSummary) AsResultRow() map[string]any {
|
|
res := map[string]any{
|
|
"uncached_rows_fetched": s.UncachedRowsFetched,
|
|
"cached_rows_fetched": s.CachedRowsFetched,
|
|
"hydrate_calls": s.HydrateCalls,
|
|
"scan_count": s.ScanCount,
|
|
"connection_count": s.ConnectionCount,
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func (s *QueryRowSummary) Update(m ScanMetadataRow) {
|
|
if m.CacheHit {
|
|
s.CachedRowsFetched += m.RowsFetched
|
|
} else {
|
|
s.UncachedRowsFetched += m.RowsFetched
|
|
}
|
|
s.HydrateCalls += m.HydrateCalls
|
|
s.ScanCount++
|
|
s.connections[m.Connection] = struct{}{}
|
|
s.ConnectionCount = int64(len(s.connections))
|
|
}
|