executeDatabaseJoinQuery executes a query against a target database for a cross-DB join. It builds a GraphQL sub-query for the child table filtered by the parent ID, compiles it using the target database's compilers, and executes it.
( ctx context.Context, dbCtx *dbContext, sel *qcode.Select, parentID []byte, )
| 140 | // It builds a GraphQL sub-query for the child table filtered by the parent ID, |
| 141 | // compiles it using the target database's compilers, and executes it. |
| 142 | func (s *gstate) executeDatabaseJoinQuery( |
| 143 | ctx context.Context, |
| 144 | dbCtx *dbContext, |
| 145 | sel *qcode.Select, |
| 146 | parentID []byte, |
| 147 | ) ([]byte, error) { |
| 148 | selects := s.cs.st.qc.Selects |
| 149 | |
| 150 | // Build a GraphQL sub-query for the child table |
| 151 | fkCol := sel.Rel.Left.Col |
| 152 | subQuery := buildChildGraphQLQuery(sel, selects, fkCol, parentID) |
| 153 | |
| 154 | // Compile QCode using the target database's compiler |
| 155 | qc, err := dbCtx.qcodeCompiler.Compile(subQuery, nil, s.role, s.r.namespace) |
| 156 | if err != nil { |
| 157 | return nil, fmt.Errorf("qcode compile failed: %w", err) |
| 158 | } |
| 159 | |
| 160 | if dbCtx.nano != nil { |
| 161 | raw, err := s.renderNanoDBQuery(dbCtx, qc) |
| 162 | if err == nil && len(raw) == 0 { |
| 163 | if sel.Singular { |
| 164 | raw = []byte(`{"` + sel.Table + `": null}`) |
| 165 | } else { |
| 166 | raw = []byte(`{"` + sel.Table + `": []}`) |
| 167 | } |
| 168 | } |
| 169 | return raw, err |
| 170 | } |
| 171 | |
| 172 | // Compile to SQL using the target database's SQL compiler |
| 173 | var sqlBuf bytes.Buffer |
| 174 | md, err := dbCtx.psqlCompiler.Compile(&sqlBuf, qc) |
| 175 | if err != nil { |
| 176 | return nil, fmt.Errorf("sql compile failed: %w", err) |
| 177 | } |
| 178 | |
| 179 | // Get a connection from the target database pool |
| 180 | conn, err := dbCtx.db.Conn(ctx) |
| 181 | if err != nil { |
| 182 | return nil, fmt.Errorf("failed to get connection: %w", err) |
| 183 | } |
| 184 | defer conn.Close() //nolint:errcheck |
| 185 | |
| 186 | // Build argument list |
| 187 | args, err := s.gj.argList(ctx, md, nil, s.r.requestconfig, false, dbCtx.psqlCompiler) |
| 188 | if err != nil { |
| 189 | return nil, fmt.Errorf("failed to build args: %w", err) |
| 190 | } |
| 191 | |
| 192 | // Execute the query |
| 193 | var data []byte |
| 194 | querySQL, queryArgs, err := prepareQueryArgsForDB(dbCtx.dbtype, sqlBuf.String(), args.values) |
| 195 | if err != nil { |
| 196 | return nil, fmt.Errorf("failed to prepare query args: %w", err) |
| 197 | } |
| 198 | |
| 199 | cacheKey := s.dbFragmentKey(ctx, fragmentKindDBJoin, dbCtx.name, querySQL, queryArgs, qc) |
no test coverage detected