| 108 | } |
| 109 | |
| 110 | func scanProcs(rows pgx.Rows) ([]Proc, error) { |
| 111 | defer rows.Close() |
| 112 | // Iterate through the result set |
| 113 | var procs []Proc |
| 114 | for rows.Next() { |
| 115 | var p Proc |
| 116 | err := rows.Scan( |
| 117 | &p.Name, |
| 118 | &p.ReturnType, |
| 119 | &p.ArgTypes, |
| 120 | &p.ArgNames, |
| 121 | &p.HasDefault, |
| 122 | &p.ArgModes, |
| 123 | ) |
| 124 | if err != nil { |
| 125 | return nil, err |
| 126 | } |
| 127 | |
| 128 | // TODO: Filter these out in SQL |
| 129 | if strings.HasPrefix(p.ReturnType, "SETOF") { |
| 130 | continue |
| 131 | } |
| 132 | |
| 133 | // The internal pseudo-type is used to declare functions that are meant |
| 134 | // only to be called internally by the database system, and not by |
| 135 | // direct invocation in an SQL query. If a function has at least one |
| 136 | // internal-type argument then it cannot be called from SQL. To |
| 137 | // preserve the type safety of this restriction it is important to |
| 138 | // follow this coding rule: do not create any function that is declared |
| 139 | // to return internal unless it has at least one internal argument |
| 140 | // |
| 141 | // https://www.postgresql.org/docs/current/datatype-pseudo.html |
| 142 | var skip bool |
| 143 | for i := range p.ArgTypes { |
| 144 | if p.ArgTypes[i] == "internal" { |
| 145 | skip = true |
| 146 | } |
| 147 | } |
| 148 | if skip { |
| 149 | continue |
| 150 | } |
| 151 | if p.ReturnType == "internal" { |
| 152 | continue |
| 153 | } |
| 154 | |
| 155 | procs = append(procs, p) |
| 156 | } |
| 157 | return procs, rows.Err() |
| 158 | } |
| 159 | |
| 160 | func readProcs(ctx context.Context, conn *pgx.Conn, schemaName string) ([]Proc, error) { |
| 161 | rows, err := conn.Query(ctx, catalogFuncs, schemaName) |