github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/norm/testdata/rules/limit (about)

     1  exec-ddl
     2  CREATE TABLE a (k INT PRIMARY KEY, i INT, f FLOAT, s STRING, j JSON)
     3  ----
     4  
     5  exec-ddl
     6  CREATE TABLE b (x INT PRIMARY KEY, y INT)
     7  ----
     8  
     9  exec-ddl
    10  CREATE TABLE ab (a INT PRIMARY KEY, b INT)
    11  ----
    12  
    13  exec-ddl
    14  CREATE TABLE uv (u INT PRIMARY KEY, v INT)
    15  ----
    16  
    17  # --------------------------------------------------
    18  # EliminateLimit
    19  # --------------------------------------------------
    20  norm expect=EliminateLimit
    21  SELECT * FROM (SELECT * FROM a LIMIT 99) LIMIT 100
    22  ----
    23  limit
    24   ├── columns: k:1!null i:2 f:3 s:4 j:5
    25   ├── cardinality: [0 - 99]
    26   ├── key: (1)
    27   ├── fd: (1)-->(2-5)
    28   ├── scan a
    29   │    ├── columns: k:1!null i:2 f:3 s:4 j:5
    30   │    ├── key: (1)
    31   │    ├── fd: (1)-->(2-5)
    32   │    └── limit hint: 99.00
    33   └── 99
    34  
    35  norm expect=EliminateLimit
    36  SELECT * FROM (SELECT * FROM a LIMIT 100) LIMIT 100
    37  ----
    38  limit
    39   ├── columns: k:1!null i:2 f:3 s:4 j:5
    40   ├── cardinality: [0 - 100]
    41   ├── key: (1)
    42   ├── fd: (1)-->(2-5)
    43   ├── scan a
    44   │    ├── columns: k:1!null i:2 f:3 s:4 j:5
    45   │    ├── key: (1)
    46   │    ├── fd: (1)-->(2-5)
    47   │    └── limit hint: 100.00
    48   └── 100
    49  
    50  # Don't eliminate the outer limit if it's less than the inner.
    51  norm
    52  SELECT * FROM (SELECT * FROM a LIMIT 100) LIMIT 99
    53  ----
    54  limit
    55   ├── columns: k:1!null i:2 f:3 s:4 j:5
    56   ├── cardinality: [0 - 99]
    57   ├── key: (1)
    58   ├── fd: (1)-->(2-5)
    59   ├── limit
    60   │    ├── columns: k:1!null i:2 f:3 s:4 j:5
    61   │    ├── cardinality: [0 - 100]
    62   │    ├── key: (1)
    63   │    ├── fd: (1)-->(2-5)
    64   │    ├── limit hint: 99.00
    65   │    ├── scan a
    66   │    │    ├── columns: k:1!null i:2 f:3 s:4 j:5
    67   │    │    ├── key: (1)
    68   │    │    ├── fd: (1)-->(2-5)
    69   │    │    └── limit hint: 100.00
    70   │    └── 100
    71   └── 99
    72  
    73  # High limits (> max uint32), can't eliminate in this case.
    74  norm
    75  SELECT * FROM (SELECT * FROM a LIMIT 5000000000) LIMIT 5100000000
    76  ----
    77  limit
    78   ├── columns: k:1!null i:2 f:3 s:4 j:5
    79   ├── key: (1)
    80   ├── fd: (1)-->(2-5)
    81   ├── limit
    82   │    ├── columns: k:1!null i:2 f:3 s:4 j:5
    83   │    ├── key: (1)
    84   │    ├── fd: (1)-->(2-5)
    85   │    ├── limit hint: 5100000000.00
    86   │    ├── scan a
    87   │    │    ├── columns: k:1!null i:2 f:3 s:4 j:5
    88   │    │    ├── key: (1)
    89   │    │    ├── fd: (1)-->(2-5)
    90   │    │    └── limit hint: 5000000000.00
    91   │    └── 5000000000
    92   └── 5100000000
    93  
    94  # Don't eliminate in case of negative limit.
    95  norm
    96  SELECT * FROM (SELECT * FROM a LIMIT 0) LIMIT -1
    97  ----
    98  limit
    99   ├── columns: k:1!null i:2!null f:3!null s:4!null j:5!null
   100   ├── cardinality: [0 - 0]
   101   ├── immutable, side-effects
   102   ├── key: ()
   103   ├── fd: ()-->(1-5)
   104   ├── values
   105   │    ├── columns: k:1!null i:2!null f:3!null s:4!null j:5!null
   106   │    ├── cardinality: [0 - 0]
   107   │    ├── key: ()
   108   │    ├── fd: ()-->(1-5)
   109   │    └── limit hint: 1.00
   110   └── -1
   111  
   112  # --------------------------------------------------
   113  # EliminateOffset
   114  # --------------------------------------------------
   115  norm expect=EliminateOffset
   116  SELECT * FROM a OFFSET 0
   117  ----
   118  scan a
   119   ├── columns: k:1!null i:2 f:3 s:4 j:5
   120   ├── key: (1)
   121   └── fd: (1)-->(2-5)
   122  
   123  norm expect=EliminateOffset
   124  SELECT * FROM a LIMIT 5 OFFSET 0
   125  ----
   126  limit
   127   ├── columns: k:1!null i:2 f:3 s:4 j:5
   128   ├── cardinality: [0 - 5]
   129   ├── key: (1)
   130   ├── fd: (1)-->(2-5)
   131   ├── scan a
   132   │    ├── columns: k:1!null i:2 f:3 s:4 j:5
   133   │    ├── key: (1)
   134   │    ├── fd: (1)-->(2-5)
   135   │    └── limit hint: 5.00
   136   └── 5
   137  
   138  norm expect-not=EliminateOffset
   139  SELECT * FROM a LIMIT 5 OFFSET 1
   140  ----
   141  offset
   142   ├── columns: k:1!null i:2 f:3 s:4 j:5
   143   ├── cardinality: [0 - 5]
   144   ├── key: (1)
   145   ├── fd: (1)-->(2-5)
   146   ├── limit
   147   │    ├── columns: k:1!null i:2 f:3 s:4 j:5
   148   │    ├── cardinality: [0 - 6]
   149   │    ├── key: (1)
   150   │    ├── fd: (1)-->(2-5)
   151   │    ├── scan a
   152   │    │    ├── columns: k:1!null i:2 f:3 s:4 j:5
   153   │    │    ├── key: (1)
   154   │    │    ├── fd: (1)-->(2-5)
   155   │    │    └── limit hint: 6.00
   156   │    └── 6
   157   └── 1
   158  
   159  # --------------------------------------------------
   160  # PushLimitIntoProject
   161  # --------------------------------------------------
   162  norm expect=PushLimitIntoProject
   163  SELECT k, f*2.0 AS r FROM a LIMIT 5
   164  ----
   165  project
   166   ├── columns: k:1!null r:6
   167   ├── cardinality: [0 - 5]
   168   ├── key: (1)
   169   ├── fd: (1)-->(6)
   170   ├── limit
   171   │    ├── columns: k:1!null f:3
   172   │    ├── cardinality: [0 - 5]
   173   │    ├── key: (1)
   174   │    ├── fd: (1)-->(3)
   175   │    ├── scan a
   176   │    │    ├── columns: k:1!null f:3
   177   │    │    ├── key: (1)
   178   │    │    ├── fd: (1)-->(3)
   179   │    │    └── limit hint: 5.00
   180   │    └── 5
   181   └── projections
   182        └── f:3 * 2.0 [as=r:6, outer=(3)]
   183  
   184  norm expect=PushLimitIntoProject
   185  SELECT k, f*2.0 AS r FROM a ORDER BY k LIMIT 5
   186  ----
   187  project
   188   ├── columns: k:1!null r:6
   189   ├── cardinality: [0 - 5]
   190   ├── key: (1)
   191   ├── fd: (1)-->(6)
   192   ├── ordering: +1
   193   ├── limit
   194   │    ├── columns: k:1!null f:3
   195   │    ├── internal-ordering: +1
   196   │    ├── cardinality: [0 - 5]
   197   │    ├── key: (1)
   198   │    ├── fd: (1)-->(3)
   199   │    ├── ordering: +1
   200   │    ├── scan a
   201   │    │    ├── columns: k:1!null f:3
   202   │    │    ├── key: (1)
   203   │    │    ├── fd: (1)-->(3)
   204   │    │    ├── ordering: +1
   205   │    │    └── limit hint: 5.00
   206   │    └── 5
   207   └── projections
   208        └── f:3 * 2.0 [as=r:6, outer=(3)]
   209  
   210  # Don't push the limit through project when the ordering is on a
   211  # synthesized column.
   212  norm expect-not=PushLimitIntoProject
   213  SELECT k, f*2.0 AS r FROM a ORDER BY r LIMIT 5
   214  ----
   215  limit
   216   ├── columns: k:1!null r:6
   217   ├── internal-ordering: +6
   218   ├── cardinality: [0 - 5]
   219   ├── key: (1)
   220   ├── fd: (1)-->(6)
   221   ├── ordering: +6
   222   ├── sort
   223   │    ├── columns: k:1!null r:6
   224   │    ├── key: (1)
   225   │    ├── fd: (1)-->(6)
   226   │    ├── ordering: +6
   227   │    ├── limit hint: 5.00
   228   │    └── project
   229   │         ├── columns: r:6 k:1!null
   230   │         ├── key: (1)
   231   │         ├── fd: (1)-->(6)
   232   │         ├── scan a
   233   │         │    ├── columns: k:1!null f:3
   234   │         │    ├── key: (1)
   235   │         │    └── fd: (1)-->(3)
   236   │         └── projections
   237   │              └── f:3 * 2.0 [as=r:6, outer=(3)]
   238   └── 5
   239  
   240  
   241  # Detect PushLimitIntoProject and FilterUnusedLimitCols dependency cycle.
   242  norm
   243  SELECT f, f+1.1 AS r FROM (SELECT f, i FROM a GROUP BY f, i) a ORDER BY f LIMIT 5
   244  ----
   245  project
   246   ├── columns: f:3 r:6
   247   ├── cardinality: [0 - 5]
   248   ├── ordering: +3
   249   ├── limit
   250   │    ├── columns: i:2 f:3
   251   │    ├── internal-ordering: +3
   252   │    ├── cardinality: [0 - 5]
   253   │    ├── key: (2,3)
   254   │    ├── ordering: +3
   255   │    ├── distinct-on
   256   │    │    ├── columns: i:2 f:3
   257   │    │    ├── grouping columns: i:2 f:3
   258   │    │    ├── key: (2,3)
   259   │    │    ├── ordering: +3
   260   │    │    ├── limit hint: 5.00
   261   │    │    └── sort
   262   │    │         ├── columns: i:2 f:3
   263   │    │         ├── ordering: +3
   264   │    │         ├── limit hint: 6.02
   265   │    │         └── scan a
   266   │    │              └── columns: i:2 f:3
   267   │    └── 5
   268   └── projections
   269        └── f:3 + 1.1 [as=r:6, outer=(3)]
   270  
   271  # Don't push negative limit into Scan.
   272  norm
   273  SELECT * FROM a LIMIT -1
   274  ----
   275  limit
   276   ├── columns: k:1!null i:2 f:3 s:4 j:5
   277   ├── cardinality: [0 - 0]
   278   ├── immutable, side-effects
   279   ├── key: ()
   280   ├── fd: ()-->(1-5)
   281   ├── scan a
   282   │    ├── columns: k:1!null i:2 f:3 s:4 j:5
   283   │    ├── key: (1)
   284   │    ├── fd: (1)-->(2-5)
   285   │    └── limit hint: 1.00
   286   └── -1
   287  
   288  # --------------------------------------------------
   289  # PushOffsetIntoProject
   290  # --------------------------------------------------
   291  norm expect=PushOffsetIntoProject
   292  SELECT k, f*2.0 AS r FROM a OFFSET 5
   293  ----
   294  project
   295   ├── columns: k:1!null r:6
   296   ├── key: (1)
   297   ├── fd: (1)-->(6)
   298   ├── offset
   299   │    ├── columns: k:1!null f:3
   300   │    ├── key: (1)
   301   │    ├── fd: (1)-->(3)
   302   │    ├── scan a
   303   │    │    ├── columns: k:1!null f:3
   304   │    │    ├── key: (1)
   305   │    │    └── fd: (1)-->(3)
   306   │    └── 5
   307   └── projections
   308        └── f:3 * 2.0 [as=r:6, outer=(3)]
   309  
   310  norm expect=PushOffsetIntoProject
   311  SELECT k, f*2.0 AS r FROM a ORDER BY k OFFSET 5
   312  ----
   313  project
   314   ├── columns: k:1!null r:6
   315   ├── key: (1)
   316   ├── fd: (1)-->(6)
   317   ├── ordering: +1
   318   ├── offset
   319   │    ├── columns: k:1!null f:3
   320   │    ├── internal-ordering: +1
   321   │    ├── key: (1)
   322   │    ├── fd: (1)-->(3)
   323   │    ├── ordering: +1
   324   │    ├── scan a
   325   │    │    ├── columns: k:1!null f:3
   326   │    │    ├── key: (1)
   327   │    │    ├── fd: (1)-->(3)
   328   │    │    └── ordering: +1
   329   │    └── 5
   330   └── projections
   331        └── f:3 * 2.0 [as=r:6, outer=(3)]
   332  
   333  # Don't push the offset through project when the ordering is on a
   334  # synthesized column.
   335  norm expect-not=PushOffsetIntoProject
   336  SELECT k, f*2.0 AS r FROM a ORDER BY r OFFSET 5
   337  ----
   338  offset
   339   ├── columns: k:1!null r:6
   340   ├── internal-ordering: +6
   341   ├── key: (1)
   342   ├── fd: (1)-->(6)
   343   ├── ordering: +6
   344   ├── sort
   345   │    ├── columns: k:1!null r:6
   346   │    ├── key: (1)
   347   │    ├── fd: (1)-->(6)
   348   │    ├── ordering: +6
   349   │    └── project
   350   │         ├── columns: r:6 k:1!null
   351   │         ├── key: (1)
   352   │         ├── fd: (1)-->(6)
   353   │         ├── scan a
   354   │         │    ├── columns: k:1!null f:3
   355   │         │    ├── key: (1)
   356   │         │    └── fd: (1)-->(3)
   357   │         └── projections
   358   │              └── f:3 * 2.0 [as=r:6, outer=(3)]
   359   └── 5
   360  
   361  # Detect PushOffsetIntoProject and FilterUnusedOffsetCols dependency cycle.
   362  norm
   363  SELECT f, f+1.1 AS r FROM (SELECT f, i FROM a GROUP BY f, i) a ORDER BY f OFFSET 5
   364  ----
   365  project
   366   ├── columns: f:3 r:6
   367   ├── ordering: +3
   368   ├── offset
   369   │    ├── columns: i:2 f:3
   370   │    ├── internal-ordering: +3
   371   │    ├── key: (2,3)
   372   │    ├── ordering: +3
   373   │    ├── distinct-on
   374   │    │    ├── columns: i:2 f:3
   375   │    │    ├── grouping columns: i:2 f:3
   376   │    │    ├── key: (2,3)
   377   │    │    ├── ordering: +3
   378   │    │    └── sort
   379   │    │         ├── columns: i:2 f:3
   380   │    │         ├── ordering: +3
   381   │    │         └── scan a
   382   │    │              └── columns: i:2 f:3
   383   │    └── 5
   384   └── projections
   385        └── f:3 + 1.1 [as=r:6, outer=(3)]
   386  
   387  # --------------------------------------------------
   388  # PushLimitIntoProject + PushOffsetIntoProject
   389  # --------------------------------------------------
   390  norm expect=(PushLimitIntoProject,PushOffsetIntoProject)
   391  SELECT k, f*2.0 AS r FROM a OFFSET 5 LIMIT 10
   392  ----
   393  project
   394   ├── columns: k:1!null r:6
   395   ├── cardinality: [0 - 10]
   396   ├── key: (1)
   397   ├── fd: (1)-->(6)
   398   ├── offset
   399   │    ├── columns: k:1!null f:3
   400   │    ├── cardinality: [0 - 10]
   401   │    ├── key: (1)
   402   │    ├── fd: (1)-->(3)
   403   │    ├── limit
   404   │    │    ├── columns: k:1!null f:3
   405   │    │    ├── cardinality: [0 - 15]
   406   │    │    ├── key: (1)
   407   │    │    ├── fd: (1)-->(3)
   408   │    │    ├── scan a
   409   │    │    │    ├── columns: k:1!null f:3
   410   │    │    │    ├── key: (1)
   411   │    │    │    ├── fd: (1)-->(3)
   412   │    │    │    └── limit hint: 15.00
   413   │    │    └── 15
   414   │    └── 5
   415   └── projections
   416        └── f:3 * 2.0 [as=r:6, outer=(3)]
   417  
   418  norm expect=(PushLimitIntoProject,PushOffsetIntoProject)
   419  SELECT f, f+1.1 AS r FROM (SELECT f, i FROM a GROUP BY f, i) a ORDER BY f OFFSET 5 LIMIT 10
   420  ----
   421  project
   422   ├── columns: f:3 r:6
   423   ├── cardinality: [0 - 10]
   424   ├── ordering: +3
   425   ├── offset
   426   │    ├── columns: i:2 f:3
   427   │    ├── internal-ordering: +3
   428   │    ├── cardinality: [0 - 10]
   429   │    ├── key: (2,3)
   430   │    ├── ordering: +3
   431   │    ├── limit
   432   │    │    ├── columns: i:2 f:3
   433   │    │    ├── internal-ordering: +3
   434   │    │    ├── cardinality: [0 - 15]
   435   │    │    ├── key: (2,3)
   436   │    │    ├── ordering: +3
   437   │    │    ├── distinct-on
   438   │    │    │    ├── columns: i:2 f:3
   439   │    │    │    ├── grouping columns: i:2 f:3
   440   │    │    │    ├── key: (2,3)
   441   │    │    │    ├── ordering: +3
   442   │    │    │    ├── limit hint: 15.00
   443   │    │    │    └── sort
   444   │    │    │         ├── columns: i:2 f:3
   445   │    │    │         ├── ordering: +3
   446   │    │    │         ├── limit hint: 18.16
   447   │    │    │         └── scan a
   448   │    │    │              └── columns: i:2 f:3
   449   │    │    └── 15
   450   │    └── 5
   451   └── projections
   452        └── f:3 + 1.1 [as=r:6, outer=(3)]
   453  
   454  # --------------------------------------------------
   455  # PushLimitIntoOffset
   456  # --------------------------------------------------
   457  
   458  norm expect=PushLimitIntoOffset
   459  SELECT k, i FROM a LIMIT 10 OFFSET 10
   460  ----
   461  offset
   462   ├── columns: k:1!null i:2
   463   ├── cardinality: [0 - 10]
   464   ├── key: (1)
   465   ├── fd: (1)-->(2)
   466   ├── limit
   467   │    ├── columns: k:1!null i:2
   468   │    ├── cardinality: [0 - 20]
   469   │    ├── key: (1)
   470   │    ├── fd: (1)-->(2)
   471   │    ├── scan a
   472   │    │    ├── columns: k:1!null i:2
   473   │    │    ├── key: (1)
   474   │    │    ├── fd: (1)-->(2)
   475   │    │    └── limit hint: 20.00
   476   │    └── 20
   477   └── 10
   478  
   479  norm expect=(PushLimitIntoOffset)
   480  SELECT k, i FROM a OFFSET 10 LIMIT 10
   481  ----
   482  offset
   483   ├── columns: k:1!null i:2
   484   ├── cardinality: [0 - 10]
   485   ├── key: (1)
   486   ├── fd: (1)-->(2)
   487   ├── limit
   488   │    ├── columns: k:1!null i:2
   489   │    ├── cardinality: [0 - 20]
   490   │    ├── key: (1)
   491   │    ├── fd: (1)-->(2)
   492   │    ├── scan a
   493   │    │    ├── columns: k:1!null i:2
   494   │    │    ├── key: (1)
   495   │    │    ├── fd: (1)-->(2)
   496   │    │    └── limit hint: 20.00
   497   │    └── 20
   498   └── 10
   499  
   500  # Limit can be pushed into the ordering if they have the same ordering.
   501  norm expect=PushLimitIntoOffset
   502  SELECT k, i FROM (SELECT k, i FROM a ORDER BY i OFFSET 20) ORDER BY i LIMIT 10
   503  ----
   504  offset
   505   ├── columns: k:1!null i:2
   506   ├── internal-ordering: +2
   507   ├── cardinality: [0 - 10]
   508   ├── key: (1)
   509   ├── fd: (1)-->(2)
   510   ├── ordering: +2
   511   ├── limit
   512   │    ├── columns: k:1!null i:2
   513   │    ├── internal-ordering: +2
   514   │    ├── cardinality: [0 - 30]
   515   │    ├── key: (1)
   516   │    ├── fd: (1)-->(2)
   517   │    ├── ordering: +2
   518   │    ├── sort
   519   │    │    ├── columns: k:1!null i:2
   520   │    │    ├── key: (1)
   521   │    │    ├── fd: (1)-->(2)
   522   │    │    ├── ordering: +2
   523   │    │    ├── limit hint: 30.00
   524   │    │    └── scan a
   525   │    │         ├── columns: k:1!null i:2
   526   │    │         ├── key: (1)
   527   │    │         └── fd: (1)-->(2)
   528   │    └── 30
   529   └── 20
   530  
   531  norm expect-not=PushLimitIntoOffset
   532  SELECT k, i FROM (SELECT k, i FROM a ORDER BY i OFFSET 20) ORDER BY i DESC LIMIT 10
   533  ----
   534  limit
   535   ├── columns: k:1!null i:2
   536   ├── internal-ordering: -2
   537   ├── cardinality: [0 - 10]
   538   ├── key: (1)
   539   ├── fd: (1)-->(2)
   540   ├── ordering: -2
   541   ├── sort
   542   │    ├── columns: k:1!null i:2
   543   │    ├── key: (1)
   544   │    ├── fd: (1)-->(2)
   545   │    ├── ordering: -2
   546   │    ├── limit hint: 10.00
   547   │    └── offset
   548   │         ├── columns: k:1!null i:2
   549   │         ├── internal-ordering: +2
   550   │         ├── key: (1)
   551   │         ├── fd: (1)-->(2)
   552   │         ├── sort
   553   │         │    ├── columns: k:1!null i:2
   554   │         │    ├── key: (1)
   555   │         │    ├── fd: (1)-->(2)
   556   │         │    ├── ordering: +2
   557   │         │    └── scan a
   558   │         │         ├── columns: k:1!null i:2
   559   │         │         ├── key: (1)
   560   │         │         └── fd: (1)-->(2)
   561   │         └── 20
   562   └── 10
   563  
   564  # Using MaxInt64. Do not apply rule when sum overflows.
   565  norm expect-not=PushLimitIntoOffset
   566  SELECT k, i FROM a LIMIT 9223372036854775807 OFFSET 9223372036854775807
   567  ----
   568  limit
   569   ├── columns: k:1!null i:2
   570   ├── key: (1)
   571   ├── fd: (1)-->(2)
   572   ├── offset
   573   │    ├── columns: k:1!null i:2
   574   │    ├── key: (1)
   575   │    ├── fd: (1)-->(2)
   576   │    ├── limit hint: 9223372036854775808.00
   577   │    ├── scan a
   578   │    │    ├── columns: k:1!null i:2
   579   │    │    ├── key: (1)
   580   │    │    ├── fd: (1)-->(2)
   581   │    │    └── limit hint: 18446744073709551616.00
   582   │    └── 9223372036854775807
   583   └── 9223372036854775807
   584  
   585  norm expect=PushLimitIntoOrdinality
   586  SELECT * FROM (SELECT * FROM a ORDER BY k) WITH ORDINALITY LIMIT 10
   587  ----
   588  ordinality
   589   ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   590   ├── cardinality: [0 - 10]
   591   ├── key: (1)
   592   ├── fd: (1)-->(2-6), (6)-->(1-5)
   593   └── limit
   594        ├── columns: k:1!null i:2 f:3 s:4 j:5
   595        ├── internal-ordering: +1
   596        ├── cardinality: [0 - 10]
   597        ├── key: (1)
   598        ├── fd: (1)-->(2-5)
   599        ├── ordering: +1
   600        ├── scan a
   601        │    ├── columns: k:1!null i:2 f:3 s:4 j:5
   602        │    ├── key: (1)
   603        │    ├── fd: (1)-->(2-5)
   604        │    ├── ordering: +1
   605        │    └── limit hint: 10.00
   606        └── 10
   607  
   608  norm expect=PushLimitIntoOrdinality
   609  SELECT * FROM a WITH ORDINALITY ORDER BY k LIMIT 10
   610  ----
   611  sort
   612   ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   613   ├── cardinality: [0 - 10]
   614   ├── key: (1)
   615   ├── fd: (1)-->(2-6), (6)-->(1-5)
   616   ├── ordering: +1
   617   └── ordinality
   618        ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   619        ├── cardinality: [0 - 10]
   620        ├── key: (1)
   621        ├── fd: (1)-->(2-6), (6)-->(1-5)
   622        └── limit
   623             ├── columns: k:1!null i:2 f:3 s:4 j:5
   624             ├── internal-ordering: +1
   625             ├── cardinality: [0 - 10]
   626             ├── key: (1)
   627             ├── fd: (1)-->(2-5)
   628             ├── scan a
   629             │    ├── columns: k:1!null i:2 f:3 s:4 j:5
   630             │    ├── key: (1)
   631             │    ├── fd: (1)-->(2-5)
   632             │    ├── ordering: +1
   633             │    └── limit hint: 10.00
   634             └── 10
   635  
   636  
   637  # More complex example of an intersection:
   638  # +(i|f) +s and +f have the intersection +(i|f) +s
   639  norm expect=PushLimitIntoOrdinality
   640  SELECT * FROM (SELECT * FROM a WHERE i=f ORDER BY i, s) WITH ORDINALITY ORDER BY f LIMIT 10
   641  ----
   642  ordinality
   643   ├── columns: k:1!null i:2!null f:3!null s:4 j:5 ordinality:6!null
   644   ├── cardinality: [0 - 10]
   645   ├── key: (1)
   646   ├── fd: (1)-->(2-6), (2)==(3), (3)==(2), (6)-->(1-5)
   647   ├── ordering: +(2|3) [actual: +2]
   648   └── limit
   649        ├── columns: k:1!null i:2!null f:3!null s:4 j:5
   650        ├── internal-ordering: +(2|3),+4
   651        ├── cardinality: [0 - 10]
   652        ├── key: (1)
   653        ├── fd: (1)-->(2-5), (2)==(3), (3)==(2)
   654        ├── ordering: +(2|3),+4 [actual: +2,+4]
   655        ├── sort
   656        │    ├── columns: k:1!null i:2!null f:3!null s:4 j:5
   657        │    ├── key: (1)
   658        │    ├── fd: (1)-->(2-5), (2)==(3), (3)==(2)
   659        │    ├── ordering: +(2|3),+4 [actual: +2,+4]
   660        │    ├── limit hint: 10.00
   661        │    └── select
   662        │         ├── columns: k:1!null i:2!null f:3!null s:4 j:5
   663        │         ├── key: (1)
   664        │         ├── fd: (1)-->(2-5), (2)==(3), (3)==(2)
   665        │         ├── scan a
   666        │         │    ├── columns: k:1!null i:2 f:3 s:4 j:5
   667        │         │    ├── key: (1)
   668        │         │    └── fd: (1)-->(2-5)
   669        │         └── filters
   670        │              └── i:2 = f:3 [outer=(2,3), constraints=(/2: (/NULL - ]; /3: (/NULL - ]), fd=(2)==(3), (3)==(2)]
   671        └── 10
   672  
   673  norm expect-not=PushLimitIntoOrdinality
   674  SELECT * FROM (SELECT * FROM a ORDER BY k) WITH ORDINALITY ORDER BY i LIMIT 10
   675  ----
   676  limit
   677   ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   678   ├── internal-ordering: +2
   679   ├── cardinality: [0 - 10]
   680   ├── key: (1)
   681   ├── fd: (1)-->(2-6), (6)-->(1-5)
   682   ├── ordering: +2
   683   ├── sort
   684   │    ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   685   │    ├── key: (1)
   686   │    ├── fd: (1)-->(2-6), (6)-->(1-5)
   687   │    ├── ordering: +2
   688   │    ├── limit hint: 10.00
   689   │    └── ordinality
   690   │         ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   691   │         ├── key: (1)
   692   │         ├── fd: (1)-->(2-6), (6)-->(1-5)
   693   │         └── scan a
   694   │              ├── columns: k:1!null i:2 f:3 s:4 j:5
   695   │              ├── key: (1)
   696   │              ├── fd: (1)-->(2-5)
   697   │              └── ordering: +1
   698   └── 10
   699  
   700  norm expect-not=PushLimitIntoOrdinality
   701  SELECT * FROM (SELECT * FROM a WITH ORDINALITY) ORDER BY ordinality LIMIT 10
   702  ----
   703  limit
   704   ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   705   ├── internal-ordering: +6
   706   ├── cardinality: [0 - 10]
   707   ├── key: (1)
   708   ├── fd: (1)-->(2-6), (6)-->(1-5)
   709   ├── ordering: +6
   710   ├── ordinality
   711   │    ├── columns: k:1!null i:2 f:3 s:4 j:5 ordinality:6!null
   712   │    ├── key: (1)
   713   │    ├── fd: (1)-->(2-6), (6)-->(1-5)
   714   │    ├── ordering: +6
   715   │    ├── limit hint: 10.00
   716   │    └── scan a
   717   │         ├── columns: k:1!null i:2 f:3 s:4 j:5
   718   │         ├── key: (1)
   719   │         ├── fd: (1)-->(2-5)
   720   │         └── limit hint: 10.00
   721   └── 10
   722  
   723  # ---------------------
   724  # PushLimitIntoLeftJoin
   725  # ---------------------
   726  
   727  norm expect=PushLimitIntoLeftJoin
   728  SELECT * FROM ab LEFT JOIN uv ON a = u LIMIT 10
   729  ----
   730  limit
   731   ├── columns: a:1!null b:2 u:3 v:4
   732   ├── cardinality: [0 - 10]
   733   ├── key: (1)
   734   ├── fd: (1)-->(2-4), (3)-->(4)
   735   ├── left-join (hash)
   736   │    ├── columns: a:1!null b:2 u:3 v:4
   737   │    ├── key: (1)
   738   │    ├── fd: (1)-->(2-4), (3)-->(4)
   739   │    ├── limit hint: 10.00
   740   │    ├── limit
   741   │    │    ├── columns: a:1!null b:2
   742   │    │    ├── cardinality: [0 - 10]
   743   │    │    ├── key: (1)
   744   │    │    ├── fd: (1)-->(2)
   745   │    │    ├── scan ab
   746   │    │    │    ├── columns: a:1!null b:2
   747   │    │    │    ├── key: (1)
   748   │    │    │    ├── fd: (1)-->(2)
   749   │    │    │    └── limit hint: 10.00
   750   │    │    └── 10
   751   │    ├── scan uv
   752   │    │    ├── columns: u:3!null v:4
   753   │    │    ├── key: (3)
   754   │    │    └── fd: (3)-->(4)
   755   │    └── filters
   756   │         └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
   757   └── 10
   758  
   759  # Ordering can be pushed down.
   760  norm expect=PushLimitIntoLeftJoin
   761  SELECT * FROM ab LEFT JOIN uv ON a = u ORDER BY a LIMIT 10
   762  ----
   763  limit
   764   ├── columns: a:1!null b:2 u:3 v:4
   765   ├── internal-ordering: +1
   766   ├── cardinality: [0 - 10]
   767   ├── key: (1)
   768   ├── fd: (1)-->(2-4), (3)-->(4)
   769   ├── ordering: +1
   770   ├── sort
   771   │    ├── columns: a:1!null b:2 u:3 v:4
   772   │    ├── key: (1)
   773   │    ├── fd: (1)-->(2-4), (3)-->(4)
   774   │    ├── ordering: +1
   775   │    ├── limit hint: 10.00
   776   │    └── left-join (hash)
   777   │         ├── columns: a:1!null b:2 u:3 v:4
   778   │         ├── key: (1)
   779   │         ├── fd: (1)-->(2-4), (3)-->(4)
   780   │         ├── limit
   781   │         │    ├── columns: a:1!null b:2
   782   │         │    ├── internal-ordering: +1
   783   │         │    ├── cardinality: [0 - 10]
   784   │         │    ├── key: (1)
   785   │         │    ├── fd: (1)-->(2)
   786   │         │    ├── scan ab
   787   │         │    │    ├── columns: a:1!null b:2
   788   │         │    │    ├── key: (1)
   789   │         │    │    ├── fd: (1)-->(2)
   790   │         │    │    ├── ordering: +1
   791   │         │    │    └── limit hint: 10.00
   792   │         │    └── 10
   793   │         ├── scan uv
   794   │         │    ├── columns: u:3!null v:4
   795   │         │    ├── key: (3)
   796   │         │    └── fd: (3)-->(4)
   797   │         └── filters
   798   │              └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
   799   └── 10
   800  
   801  norm expect=PushLimitIntoLeftJoin
   802  SELECT * FROM ab LEFT JOIN uv ON a = u ORDER BY b LIMIT 10
   803  ----
   804  limit
   805   ├── columns: a:1!null b:2 u:3 v:4
   806   ├── internal-ordering: +2
   807   ├── cardinality: [0 - 10]
   808   ├── key: (1)
   809   ├── fd: (1)-->(2-4), (3)-->(4)
   810   ├── ordering: +2
   811   ├── sort
   812   │    ├── columns: a:1!null b:2 u:3 v:4
   813   │    ├── key: (1)
   814   │    ├── fd: (1)-->(2-4), (3)-->(4)
   815   │    ├── ordering: +2
   816   │    ├── limit hint: 10.00
   817   │    └── left-join (hash)
   818   │         ├── columns: a:1!null b:2 u:3 v:4
   819   │         ├── key: (1)
   820   │         ├── fd: (1)-->(2-4), (3)-->(4)
   821   │         ├── limit
   822   │         │    ├── columns: a:1!null b:2
   823   │         │    ├── internal-ordering: +2
   824   │         │    ├── cardinality: [0 - 10]
   825   │         │    ├── key: (1)
   826   │         │    ├── fd: (1)-->(2)
   827   │         │    ├── sort
   828   │         │    │    ├── columns: a:1!null b:2
   829   │         │    │    ├── key: (1)
   830   │         │    │    ├── fd: (1)-->(2)
   831   │         │    │    ├── ordering: +2
   832   │         │    │    ├── limit hint: 10.00
   833   │         │    │    └── scan ab
   834   │         │    │         ├── columns: a:1!null b:2
   835   │         │    │         ├── key: (1)
   836   │         │    │         └── fd: (1)-->(2)
   837   │         │    └── 10
   838   │         ├── scan uv
   839   │         │    ├── columns: u:3!null v:4
   840   │         │    ├── key: (3)
   841   │         │    └── fd: (3)-->(4)
   842   │         └── filters
   843   │              └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
   844   └── 10
   845  
   846  # Ordering on u is not equivalent to ordering on a because of NULLs; it cannot
   847  # be pushed down.
   848  norm expect-not=PushLimitIntoLeftJoin
   849  SELECT * FROM ab LEFT JOIN uv ON a = u ORDER BY u LIMIT 10
   850  ----
   851  limit
   852   ├── columns: a:1!null b:2 u:3 v:4
   853   ├── internal-ordering: +3
   854   ├── cardinality: [0 - 10]
   855   ├── key: (1)
   856   ├── fd: (1)-->(2-4), (3)-->(4)
   857   ├── ordering: +3
   858   ├── sort
   859   │    ├── columns: a:1!null b:2 u:3 v:4
   860   │    ├── key: (1)
   861   │    ├── fd: (1)-->(2-4), (3)-->(4)
   862   │    ├── ordering: +3
   863   │    ├── limit hint: 10.00
   864   │    └── left-join (hash)
   865   │         ├── columns: a:1!null b:2 u:3 v:4
   866   │         ├── key: (1)
   867   │         ├── fd: (1)-->(2-4), (3)-->(4)
   868   │         ├── scan ab
   869   │         │    ├── columns: a:1!null b:2
   870   │         │    ├── key: (1)
   871   │         │    └── fd: (1)-->(2)
   872   │         ├── scan uv
   873   │         │    ├── columns: u:3!null v:4
   874   │         │    ├── key: (3)
   875   │         │    └── fd: (3)-->(4)
   876   │         └── filters
   877   │              └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
   878   └── 10
   879  
   880  # Ordering cannot be pushed down.
   881  norm expect-not=PushLimitIntoLeftJoin
   882  SELECT * FROM ab LEFT JOIN uv ON a = u ORDER BY v LIMIT 10
   883  ----
   884  limit
   885   ├── columns: a:1!null b:2 u:3 v:4
   886   ├── internal-ordering: +4
   887   ├── cardinality: [0 - 10]
   888   ├── key: (1)
   889   ├── fd: (1)-->(2-4), (3)-->(4)
   890   ├── ordering: +4
   891   ├── sort
   892   │    ├── columns: a:1!null b:2 u:3 v:4
   893   │    ├── key: (1)
   894   │    ├── fd: (1)-->(2-4), (3)-->(4)
   895   │    ├── ordering: +4
   896   │    ├── limit hint: 10.00
   897   │    └── left-join (hash)
   898   │         ├── columns: a:1!null b:2 u:3 v:4
   899   │         ├── key: (1)
   900   │         ├── fd: (1)-->(2-4), (3)-->(4)
   901   │         ├── scan ab
   902   │         │    ├── columns: a:1!null b:2
   903   │         │    ├── key: (1)
   904   │         │    └── fd: (1)-->(2)
   905   │         ├── scan uv
   906   │         │    ├── columns: u:3!null v:4
   907   │         │    ├── key: (3)
   908   │         │    └── fd: (3)-->(4)
   909   │         └── filters
   910   │              └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
   911   └── 10
   912  
   913  norm expect-not=PushLimitIntoLeftJoin
   914  SELECT * FROM ab LEFT JOIN uv ON b = v ORDER BY a, v LIMIT 10
   915  ----
   916  limit
   917   ├── columns: a:1!null b:2 u:3 v:4
   918   ├── internal-ordering: +1,+4
   919   ├── cardinality: [0 - 10]
   920   ├── key: (1,3)
   921   ├── fd: (1)-->(2), (3)-->(4)
   922   ├── ordering: +1,+4
   923   ├── sort
   924   │    ├── columns: a:1!null b:2 u:3 v:4
   925   │    ├── key: (1,3)
   926   │    ├── fd: (1)-->(2), (3)-->(4)
   927   │    ├── ordering: +1,+4
   928   │    ├── limit hint: 10.00
   929   │    └── left-join (hash)
   930   │         ├── columns: a:1!null b:2 u:3 v:4
   931   │         ├── key: (1,3)
   932   │         ├── fd: (1)-->(2), (3)-->(4)
   933   │         ├── scan ab
   934   │         │    ├── columns: a:1!null b:2
   935   │         │    ├── key: (1)
   936   │         │    └── fd: (1)-->(2)
   937   │         ├── scan uv
   938   │         │    ├── columns: u:3!null v:4
   939   │         │    ├── key: (3)
   940   │         │    └── fd: (3)-->(4)
   941   │         └── filters
   942   │              └── b:2 = v:4 [outer=(2,4), constraints=(/2: (/NULL - ]; /4: (/NULL - ]), fd=(2)==(4), (4)==(2)]
   943   └── 10
   944  
   945  norm expect-not=PushLimitIntoLeftJoin
   946  SELECT * FROM ab LEFT JOIN uv ON a = u ORDER BY u, b LIMIT 10
   947  ----
   948  limit
   949   ├── columns: a:1!null b:2 u:3 v:4
   950   ├── internal-ordering: +3,+2
   951   ├── cardinality: [0 - 10]
   952   ├── key: (1)
   953   ├── fd: (1)-->(2-4), (3)-->(4)
   954   ├── ordering: +3,+2
   955   ├── sort
   956   │    ├── columns: a:1!null b:2 u:3 v:4
   957   │    ├── key: (1)
   958   │    ├── fd: (1)-->(2-4), (3)-->(4)
   959   │    ├── ordering: +3,+2
   960   │    ├── limit hint: 10.00
   961   │    └── left-join (hash)
   962   │         ├── columns: a:1!null b:2 u:3 v:4
   963   │         ├── key: (1)
   964   │         ├── fd: (1)-->(2-4), (3)-->(4)
   965   │         ├── scan ab
   966   │         │    ├── columns: a:1!null b:2
   967   │         │    ├── key: (1)
   968   │         │    └── fd: (1)-->(2)
   969   │         ├── scan uv
   970   │         │    ├── columns: u:3!null v:4
   971   │         │    ├── key: (3)
   972   │         │    └── fd: (3)-->(4)
   973   │         └── filters
   974   │              └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
   975   └── 10
   976  
   977  # Rule should not fire if the input's cardinality is already less than the
   978  # limit.
   979  norm expect-not=PushLimitIntoLeftJoin
   980  SELECT * FROM (SELECT * FROM ab LIMIT 5) LEFT JOIN uv ON a = u LIMIT 10
   981  ----
   982  limit
   983   ├── columns: a:1!null b:2 u:3 v:4
   984   ├── cardinality: [0 - 10]
   985   ├── key: (1)
   986   ├── fd: (1)-->(2-4), (3)-->(4)
   987   ├── left-join (hash)
   988   │    ├── columns: a:1!null b:2 u:3 v:4
   989   │    ├── key: (1)
   990   │    ├── fd: (1)-->(2-4), (3)-->(4)
   991   │    ├── limit hint: 10.00
   992   │    ├── limit
   993   │    │    ├── columns: a:1!null b:2
   994   │    │    ├── cardinality: [0 - 5]
   995   │    │    ├── key: (1)
   996   │    │    ├── fd: (1)-->(2)
   997   │    │    ├── scan ab
   998   │    │    │    ├── columns: a:1!null b:2
   999   │    │    │    ├── key: (1)
  1000   │    │    │    ├── fd: (1)-->(2)
  1001   │    │    │    └── limit hint: 5.00
  1002   │    │    └── 5
  1003   │    ├── scan uv
  1004   │    │    ├── columns: u:3!null v:4
  1005   │    │    ├── key: (3)
  1006   │    │    └── fd: (3)-->(4)
  1007   │    └── filters
  1008   │         └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
  1009   └── 10
  1010  
  1011  # Push the limit even if the input is already limited (but with a higher limit).
  1012  norm expect=PushLimitIntoLeftJoin
  1013  SELECT * FROM (SELECT * FROM ab LIMIT 20) LEFT JOIN uv ON a = u LIMIT 10
  1014  ----
  1015  limit
  1016   ├── columns: a:1!null b:2 u:3 v:4
  1017   ├── cardinality: [0 - 10]
  1018   ├── key: (1)
  1019   ├── fd: (1)-->(2-4), (3)-->(4)
  1020   ├── left-join (hash)
  1021   │    ├── columns: a:1!null b:2 u:3 v:4
  1022   │    ├── key: (1)
  1023   │    ├── fd: (1)-->(2-4), (3)-->(4)
  1024   │    ├── limit hint: 10.00
  1025   │    ├── limit
  1026   │    │    ├── columns: a:1!null b:2
  1027   │    │    ├── cardinality: [0 - 10]
  1028   │    │    ├── key: (1)
  1029   │    │    ├── fd: (1)-->(2)
  1030   │    │    ├── limit
  1031   │    │    │    ├── columns: a:1!null b:2
  1032   │    │    │    ├── cardinality: [0 - 20]
  1033   │    │    │    ├── key: (1)
  1034   │    │    │    ├── fd: (1)-->(2)
  1035   │    │    │    ├── limit hint: 10.00
  1036   │    │    │    ├── scan ab
  1037   │    │    │    │    ├── columns: a:1!null b:2
  1038   │    │    │    │    ├── key: (1)
  1039   │    │    │    │    ├── fd: (1)-->(2)
  1040   │    │    │    │    └── limit hint: 20.00
  1041   │    │    │    └── 20
  1042   │    │    └── 10
  1043   │    ├── scan uv
  1044   │    │    ├── columns: u:3!null v:4
  1045   │    │    ├── key: (3)
  1046   │    │    └── fd: (3)-->(4)
  1047   │    └── filters
  1048   │         └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
  1049   └── 10
  1050  
  1051  # Don't push negative limits (or we would enter an infinite loop).
  1052  norm expect-not=PushLimitIntoLeftJoin
  1053  SELECT * FROM ab LEFT JOIN uv ON a = u LIMIT -1
  1054  ----
  1055  limit
  1056   ├── columns: a:1!null b:2 u:3 v:4
  1057   ├── cardinality: [0 - 0]
  1058   ├── immutable, side-effects
  1059   ├── key: ()
  1060   ├── fd: ()-->(1-4)
  1061   ├── left-join (hash)
  1062   │    ├── columns: a:1!null b:2 u:3 v:4
  1063   │    ├── key: (1)
  1064   │    ├── fd: (1)-->(2-4), (3)-->(4)
  1065   │    ├── limit hint: 1.00
  1066   │    ├── scan ab
  1067   │    │    ├── columns: a:1!null b:2
  1068   │    │    ├── key: (1)
  1069   │    │    └── fd: (1)-->(2)
  1070   │    ├── scan uv
  1071   │    │    ├── columns: u:3!null v:4
  1072   │    │    ├── key: (3)
  1073   │    │    └── fd: (3)-->(4)
  1074   │    └── filters
  1075   │         └── a:1 = u:3 [outer=(1,3), constraints=(/1: (/NULL - ]; /3: (/NULL - ]), fd=(1)==(3), (3)==(1)]
  1076   └── -1