HasNeighborsWith applies on the given Selector a neighbors check. The given predicate applies its filtering on the selector.
(q *sql.Selector, s *Step, pred func(*sql.Selector))
| 279 | // HasNeighborsWith applies on the given Selector a neighbors check. |
| 280 | // The given predicate applies its filtering on the selector. |
| 281 | func HasNeighborsWith(q *sql.Selector, s *Step, pred func(*sql.Selector)) { |
| 282 | builder := sql.Dialect(q.Dialect()) |
| 283 | switch { |
| 284 | case s.ThroughEdgeTable(): |
| 285 | pk1, pk2 := s.Edge.Columns[1], s.Edge.Columns[0] |
| 286 | if s.Edge.Inverse { |
| 287 | pk1, pk2 = pk2, pk1 |
| 288 | } |
| 289 | to := builder.Table(s.To.Table).Schema(s.To.Schema) |
| 290 | edge := builder.Table(s.Edge.Table).Schema(s.Edge.Schema) |
| 291 | join := builder.Select(edge.C(pk2)). |
| 292 | From(edge). |
| 293 | Join(to). |
| 294 | On(edge.C(pk1), to.C(s.To.Column)) |
| 295 | matches := builder.Select().From(to) |
| 296 | matches.WithContext(q.Context()) |
| 297 | pred(matches) |
| 298 | join.FromSelect(matches) |
| 299 | q.Where(sql.In(q.C(s.From.Column), join)) |
| 300 | case s.FromEdgeOwner(): |
| 301 | to := builder.Table(s.To.Table).Schema(s.To.Schema) |
| 302 | // Avoid ambiguity in case both source |
| 303 | // and edge tables are the same. |
| 304 | if s.To.Table == q.TableName() { |
| 305 | to.As(fmt.Sprintf("%s_edge", s.To.Table)) |
| 306 | // Choose the alias name until we do not |
| 307 | // have a collision. Limit to 5 iterations. |
| 308 | for i := 1; i <= 5; i++ { |
| 309 | if to.C("c") != q.C("c") { |
| 310 | break |
| 311 | } |
| 312 | to.As(fmt.Sprintf("%s_edge_%d", s.To.Table, i)) |
| 313 | } |
| 314 | } |
| 315 | matches := builder.Select(to.C(s.To.Column)). |
| 316 | From(to) |
| 317 | matches.WithContext(q.Context()) |
| 318 | matches.Where( |
| 319 | sql.ColumnsEQ( |
| 320 | q.C(s.Edge.Columns[0]), |
| 321 | to.C(s.To.Column), |
| 322 | ), |
| 323 | ) |
| 324 | pred(matches) |
| 325 | q.Where(sql.Exists(matches)) |
| 326 | case s.ToEdgeOwner(): |
| 327 | to := builder.Table(s.Edge.Table).Schema(s.Edge.Schema) |
| 328 | // Avoid ambiguity in case both source |
| 329 | // and edge tables are the same. |
| 330 | if s.Edge.Table == q.TableName() { |
| 331 | to.As(fmt.Sprintf("%s_edge", s.Edge.Table)) |
| 332 | // Choose the alias name until we do not |
| 333 | // have a collision. Limit to 5 iterations. |
| 334 | for i := 1; i <= 5; i++ { |
| 335 | if to.C("c") != q.C("c") { |
| 336 | break |
| 337 | } |
| 338 | to.As(fmt.Sprintf("%s_edge_%d", s.Edge.Table, i)) |
searching dependent graphs…