github.com/octohelm/storage@v0.0.0-20240516030302-1ac2cc1ea347/pkg/sqlbuilder/stmt_with_test.go (about)

     1  package sqlbuilder_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/octohelm/storage/internal/testutil"
     7  	. "github.com/octohelm/storage/pkg/sqlbuilder"
     8  )
     9  
    10  func TestWithStmt(t *testing.T) {
    11  	gr := &GroupRelation{}
    12  	g := &Group{}
    13  
    14  	t.Run("simple with", func(t *testing.T) {
    15  		testutil.ShouldBeExpr(t,
    16  			With((&GroupWithParent{}).T(), func(tmpTableGroupWithParent Table) SqlExpr {
    17  				s := Select(MultiMayAutoAlias(
    18  					TypedColOf[int](g.T(), "f_group_id"),
    19  					TypedColOf[int](gr.T(), "f_group_id"),
    20  				)).
    21  					From(gr.T(),
    22  						RightJoin(g.T()).On(
    23  							TypedColOf[int](g.T(), "f_group_id").V(EqCol(TypedColOf[int](gr.T(), "f_group_id")))),
    24  					)
    25  				return s
    26  			}).With((&GroupWithParent{}).T(), func(tmpTableGroupWithParent Table) SqlExpr {
    27  				s := Select(MultiMayAutoAlias(
    28  					TypedColOf[int](g.T(), "f_group_id"),
    29  					TypedColOf[int](gr.T(), "f_group_id"),
    30  				)).
    31  					From(gr.T(),
    32  						RightJoin(g.T()).On(
    33  							TypedColOf[int](g.T(), "f_group_id").V(
    34  								EqCol(TypedColOf[int](gr.T(), "f_group_id")),
    35  							),
    36  						),
    37  					)
    38  				return s
    39  			}).
    40  				Exec(func(tables ...Table) SqlExpr {
    41  					return Select(nil).From(tables[0])
    42  				}),
    43  			`
    44  WITH t_group_with_parent(f_group_id,f_parent_group_id) AS (
    45  SELECT t_group.f_group_id AS t_group__f_group_id, t_group_relation.f_group_id AS t_group_relation__f_group_id FROM t_group_relation
    46  RIGHT JOIN t_group ON t_group.f_group_id = t_group_relation.f_group_id
    47  ), t_group_with_parent(f_group_id,f_parent_group_id) AS (
    48  SELECT t_group.f_group_id AS t_group__f_group_id, t_group_relation.f_group_id AS t_group_relation__f_group_id FROM t_group_relation
    49  RIGHT JOIN t_group ON t_group.f_group_id = t_group_relation.f_group_id
    50  )
    51  SELECT * FROM t_group_with_parent
    52  `)
    53  	})
    54  	t.Run("WithRecursive", func(t *testing.T) {
    55  		testutil.ShouldBeExpr(t,
    56  			WithRecursive((&GroupWithParentAndChildren{}).T(), func(tmpTableGroupWithParentAndChildren Table) SqlExpr {
    57  				return With((&GroupWithParent{}).T(), func(tmpTableGroupWithParent Table) SqlExpr {
    58  					s := Select(MultiMayAutoAlias(
    59  						TypedColOf[int](g.T(), "f_group_id"),
    60  						TypedColOf[int](gr.T(), "f_parent_group_id"),
    61  					)).
    62  						From(gr.T(), RightJoin(g.T()).On(
    63  							TypedColOf[int](g.T(), "f_group_id").V(
    64  								EqCol(TypedColOf[int](gr.T(), "f_group_id"))),
    65  						))
    66  					return s
    67  				}).Exec(func(tables ...Table) SqlExpr {
    68  					tmpTableGroupWithParent := tables[0]
    69  					return Select(
    70  						MultiMayAutoAlias(
    71  							tmpTableGroupWithParent.F("f_group_id"),
    72  							tmpTableGroupWithParent.F("f_parent_group_id"),
    73  							Alias(Expr("0"), "f_depth"),
    74  						),
    75  					).From(
    76  						tmpTableGroupWithParent,
    77  						Where(
    78  							TypedColOf[int](tmpTableGroupWithParent, "f_group_id").V(Eq(1201375536060956676)),
    79  						),
    80  						Union().All(
    81  							Select(MultiMayAutoAlias(
    82  								tmpTableGroupWithParent.F("f_group_id"),
    83  								tmpTableGroupWithParent.F("f_parent_group_id"),
    84  								Alias(tmpTableGroupWithParentAndChildren.F("f_depth").Expr("# + 1"), "f_depth"),
    85  							)).From(
    86  								tmpTableGroupWithParent,
    87  								CrossJoin(tmpTableGroupWithParentAndChildren),
    88  								Where(
    89  									And(
    90  										TypedColOf[int](tmpTableGroupWithParent, "f_group_id").V(NeqCol(TypedColOf[int](tmpTableGroupWithParentAndChildren, "f_group_id"))),
    91  										TypedColOf[int](tmpTableGroupWithParent, "f_parent_group_id").V(EqCol(TypedColOf[int](tmpTableGroupWithParentAndChildren, "f_group_id"))),
    92  									),
    93  								),
    94  							),
    95  						),
    96  					)
    97  				})
    98  			}).Exec(func(tables ...Table) SqlExpr {
    99  				return Select(nil).From(tables[0])
   100  			}),
   101  			`
   102  WITH RECURSIVE t_group_with_parent_and_children(f_group_id,f_parent_group_id,f_depth) AS (
   103  WITH t_group_with_parent(f_group_id,f_parent_group_id) AS (
   104  SELECT t_group.f_group_id AS t_group__f_group_id, t_group_relation.f_parent_group_id AS t_group_relation__f_parent_group_id FROM t_group_relation
   105  RIGHT JOIN t_group ON t_group.f_group_id = t_group_relation.f_group_id
   106  )
   107  SELECT f_group_id, f_parent_group_id, 0 AS f_depth FROM t_group_with_parent
   108  WHERE f_group_id = ?
   109  UNION ALL SELECT t_group_with_parent.f_group_id AS t_group_with_parent__f_group_id, t_group_with_parent.f_parent_group_id AS t_group_with_parent__f_parent_group_id, t_group_with_parent_and_children.f_depth + 1 AS f_depth FROM t_group_with_parent
   110  CROSS JOIN t_group_with_parent_and_children
   111  WHERE (t_group_with_parent.f_group_id <> t_group_with_parent_and_children.f_group_id) AND (t_group_with_parent.f_parent_group_id = t_group_with_parent_and_children.f_group_id)
   112  )
   113  SELECT * FROM t_group_with_parent_and_children
   114  `, 1201375536060956676)
   115  	})
   116  }
   117  
   118  var tableGroup = TableFromModel(&Group{})
   119  
   120  type Group struct {
   121  	GroupID int `db:"f_group_id"`
   122  }
   123  
   124  func (g *Group) TableName() string {
   125  	return "t_group"
   126  }
   127  
   128  func (g *Group) T() Table {
   129  	return tableGroup
   130  }
   131  
   132  var tableGroupRelation = TableFromModel(&GroupRelation{})
   133  
   134  type GroupRelation struct {
   135  	GroupID       int `db:"f_group_id"`
   136  	ParentGroupID int `db:"f_parent_group_id"`
   137  }
   138  
   139  func (g *GroupRelation) TableName() string {
   140  	return "t_group_relation"
   141  }
   142  
   143  func (g *GroupRelation) T() Table {
   144  	return tableGroupRelation
   145  }
   146  
   147  var tableGroupWithParent = TableFromModel(&GroupWithParent{})
   148  
   149  type GroupWithParent struct {
   150  	GroupID       int `db:"f_group_id"`
   151  	ParentGroupID int `db:"f_parent_group_id"`
   152  }
   153  
   154  func (g *GroupWithParent) TableName() string {
   155  	return "t_group_with_parent"
   156  }
   157  
   158  func (g *GroupWithParent) T() Table {
   159  	return tableGroupWithParent
   160  }
   161  
   162  var tableGroupWithParentAndChildren = TableFromModel(&GroupWithParentAndChildren{})
   163  
   164  type GroupWithParentAndChildren struct {
   165  	GroupWithParent
   166  	Depth int `db:"f_depth"`
   167  }
   168  
   169  func (g *GroupWithParentAndChildren) TableName() string {
   170  	return "t_group_with_parent_and_children"
   171  }
   172  
   173  func (g *GroupWithParentAndChildren) T() Table {
   174  	return tableGroupWithParentAndChildren
   175  }