Skip to content

Commit 5924aa5

Browse files
committed
Merge branch 'v1.12.x' into develop
2 parents 53e4f3c + cfb694a commit 5924aa5

File tree

7 files changed

+1823
-953
lines changed

7 files changed

+1823
-953
lines changed

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ PLATFORM=$(shell uname)
77
GETTEXT_INCLUDE=$(shell dirname $(shell dirname $(shell readlink -f $(shell which gettext))))/include
88

99
install: build
10-
if test -d ~/.steampipe/db/14.2.0; then \
11-
cp ./build-$(PLATFORM)/steampipe_postgres_fdw--1.0.sql $(STEAMPIPE_INSTALL_DIR)/db/14.2.0/postgres/share/postgresql/extension/; \
12-
cp ./build-$(PLATFORM)/steampipe_postgres_fdw.control $(STEAMPIPE_INSTALL_DIR)/db/14.2.0/postgres/share/postgresql/extension/; \
13-
cp ./build-$(PLATFORM)/steampipe_postgres_fdw.so $(STEAMPIPE_INSTALL_DIR)/db/14.2.0/postgres/lib/postgresql/; \
10+
if test -d ~/.steampipe/db/14.17.0; then \
11+
cp ./build-$(PLATFORM)/steampipe_postgres_fdw--1.0.sql $(STEAMPIPE_INSTALL_DIR)/db/14.17.0/postgres/share/postgresql/extension/; \
12+
cp ./build-$(PLATFORM)/steampipe_postgres_fdw.control $(STEAMPIPE_INSTALL_DIR)/db/14.17.0/postgres/share/postgresql/extension/; \
13+
cp ./build-$(PLATFORM)/steampipe_postgres_fdw.so $(STEAMPIPE_INSTALL_DIR)/db/14.17.0/postgres/lib/postgresql/; \
1414
fi
1515

1616
# build standalone

fdw.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import (
1818
"fmt"
1919
"io"
2020
"log"
21+
"net"
22+
"net/http"
23+
"os"
2124
"time"
2225
"unsafe"
2326

@@ -71,6 +74,18 @@ func init() {
7174
log.Printf("[INFO] Version: v%s\n", version.FdwVersion.String())
7275
log.Printf("[INFO] Log level: %s\n", level)
7376

77+
if _, found := os.LookupEnv("STEAMPIPE_FDW_PPROF"); found {
78+
log.Printf("[INFO] PROFILING!!!!")
79+
go func() {
80+
listener, err := net.Listen("tcp", "localhost:0")
81+
if err != nil {
82+
log.Println(err)
83+
return
84+
}
85+
log.Printf("[INFO] Check http://localhost:%d/debug/pprof/", listener.Addr().(*net.TCPAddr).Port)
86+
log.Println(http.Serve(listener, nil))
87+
}()
88+
}
7489
}
7590

7691
// Given a list of FdwDeparsedSortGroup and a FdwPlanState,

go.mod

Lines changed: 131 additions & 119 deletions
Large diffs are not rendered by default.

go.sum

Lines changed: 1012 additions & 251 deletions
Large diffs are not rendered by default.

types/pathkeys.go

Lines changed: 64 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -57,64 +57,99 @@ func keyColumnArrayContainsColumn(keyColumns []*proto.KeyColumn, c string) bool
5757
}
5858

5959
// keyColumnsToColumnPath returns a list of all the column sets to use in path keys
60-
func keyColumnsToColumnPath(keyColumns []*proto.KeyColumn) (columnPaths [][]string, baseCost Cost) {
60+
func keyColumnsToColumnPath(keyColumns []*proto.KeyColumn) ([][]string, Cost) {
61+
var columnPaths [][]string
62+
var baseCost Cost
63+
6164
if len(keyColumns) == 0 {
62-
return
65+
return columnPaths, baseCost
6366
}
6467

65-
// collect required and optional columns - we build a single path for all of them
66-
var requiredKeys, optionalKeys []string
67-
// an array of paths for any of keys - each path will have a single element (the any-of key)
68-
var anyOfKeys [][]string
68+
// collect required and optional and any of keys
69+
var requiredKeys, optionalKeys, anyOfKeys []string
6970
for _, c := range keyColumns {
7071
if c.Require == plugin.Required {
7172
requiredKeys = append(requiredKeys, c.Name)
7273
} else if c.Require == plugin.Optional {
7374
optionalKeys = append(optionalKeys, c.Name)
7475
} else if c.Require == plugin.AnyOf {
75-
anyOfKeys = append(anyOfKeys, []string{c.Name})
76+
anyOfKeys = append(anyOfKeys, c.Name)
7677
}
7778
}
7879

79-
if len(requiredKeys) > 0 {
80-
// add required keys as a single path
81-
columnPaths = append(columnPaths, requiredKeys)
82-
}
80+
var requiredColumnPaths [][]string
81+
// if we have any-of keys, for each any-of key we will create a separate path containing that key and all required keys
8382
if len(anyOfKeys) > 0 {
84-
// add a separate path for _each_ any-of key
85-
columnPaths = append(columnPaths, anyOfKeys...)
83+
for _, a := range anyOfKeys {
84+
columnPath := append([]string{a}, requiredKeys...)
85+
requiredColumnPaths = append(requiredColumnPaths, columnPath)
86+
}
87+
} else if len(requiredKeys) > 0 {
88+
// add required keys as a single path
89+
requiredColumnPaths = append(requiredColumnPaths, requiredKeys)
8690
}
91+
8792
// if we have any column paths (meaning we have aither required or any-of columns),
8893
// we have required keys so make the base cost CHEAP
89-
if len(columnPaths) > 0 {
94+
if len(requiredColumnPaths) > 0 {
9095
baseCost = requiredKeyColumnBaseCost
9196
} else {
9297
baseCost = optionalKeyColumnBaseCost
9398
}
94-
// if there are optional keys, add:
95-
// - a path with required keys and each optional key
96-
// - a path with each any-of key and each optional key
99+
100+
// create output column paths - init to the required column paths - we will add permutations with optional keys
101+
columnPaths = requiredColumnPaths
102+
// now create additional paths based on the required paths, with each of the optional keys
97103
for _, optional := range optionalKeys {
104+
col := optional
98105
// NOTE: append onto optional, NOT requiredKeys - otherwise we end up reusing the underlying array
99106
// and mutating values in columnPaths
100107

101108
// if there are any required keys, build path from optional AND required
102-
if len(requiredKeys) > 0 {
103-
p := append([]string{optional}, requiredKeys...)
104-
columnPaths = append(columnPaths, p)
105-
}
106-
// if there are any anyOf keys, build path from optional AND required
107-
for _, a := range anyOfKeys {
108-
p := append([]string{optional}, a...)
109-
columnPaths = append(columnPaths, p)
109+
if len(requiredColumnPaths) > 0 {
110+
for _, requiredPath := range requiredColumnPaths {
111+
p := append(append([]string{}, requiredPath...), col)
112+
columnPaths = append(columnPaths, p)
113+
}
114+
} else {
115+
// if there are no required keys or anyof keys, just create a path from the optional
116+
columnPaths = append(columnPaths, []string{col})
110117
}
111-
// if there are no required keys or anyof keys, just create a path from the optional
112-
if baseCost == optionalKeyColumnBaseCost {
113-
columnPaths = append(columnPaths, []string{optional})
118+
}
119+
120+
return columnPaths, baseCost
121+
}
122+
123+
func columnPathsToPathKeys(columnPaths [][]string, allColumns []string, baseCost Cost) []PathKey {
124+
125+
var res []PathKey
126+
127+
// generate path keys each column set
128+
for _, s := range columnPaths {
129+
// create a path for just the column path
130+
res = append(res, PathKey{
131+
ColumnNames: s,
132+
// make this cheap so the planner prefers to give us the qual
133+
Rows: baseCost * keyColumnOnlyCostMultiplier,
134+
})
135+
// also create paths for the columns path WITH each other column
136+
for _, c := range allColumns {
137+
if !slices.Contains(s, c) {
138+
// NOTE: create a new slice rather than appending onto s - to avoid clash between loop iterations
139+
columnNames := append([]string{c}, s...)
140+
141+
res = append(res, PathKey{
142+
ColumnNames: columnNames,
143+
// make this even cheaper - prefer to include all quals which were provided
144+
Rows: baseCost,
145+
})
146+
}
114147
}
115148
}
116149

117-
return
150+
log.Printf("[TRACE] columnPathsToPathKeys %d column paths %d all columns, %d pathkeys", len(columnPaths), len(allColumns), len(res))
151+
152+
return res
118153
}
119154

120155
func LegacyKeyColumnsToPathKeys(requiredColumns, optionalColumns *proto.KeyColumnsSet, allColumns []string) []PathKey {
@@ -155,34 +190,3 @@ func LegacyKeyColumnsToColumnPaths(k *proto.KeyColumnsSet) [][]string {
155190
}
156191
return res
157192
}
158-
func columnPathsToPathKeys(columnPaths [][]string, allColumns []string, baseCost Cost) []PathKey {
159-
160-
var res []PathKey
161-
162-
// generate path keys each column set
163-
for _, s := range columnPaths {
164-
// create a path for just the column path
165-
res = append(res, PathKey{
166-
ColumnNames: s,
167-
// make this cheap so the planner prefers to give us the qual
168-
Rows: baseCost * keyColumnOnlyCostMultiplier,
169-
})
170-
// also create paths for the columns path WITH each other column
171-
for _, c := range allColumns {
172-
if !slices.Contains(s, c) {
173-
// NOTE: create a new slice rather than appending onto s - to avoid clash between loop iterations
174-
columnNames := append([]string{c}, s...)
175-
176-
res = append(res, PathKey{
177-
ColumnNames: columnNames,
178-
// make this even cheaper - prefer to include all quals which were provided
179-
Rows: baseCost,
180-
})
181-
}
182-
}
183-
}
184-
185-
log.Printf("[TRACE] columnPathsToPathKeys %d column paths %d all columns, %d pathkeys", len(columnPaths), len(allColumns), len(res))
186-
187-
return res
188-
}

0 commit comments

Comments
 (0)