/ Hex Artifact Content
Login

Artifact aceb80ab927d46fba5ce7586ebabf23e2bb0604f:


0000: 23 20 32 30 31 30 20 53 65 70 74 65 6d 62 65 72  # 2010 September
0010: 20 32 34 0a 23 0a 23 20 54 68 65 20 61 75 74 68   24.#.# The auth
0020: 6f 72 20 64 69 73 63 6c 61 69 6d 73 20 63 6f 70  or disclaims cop
0030: 79 72 69 67 68 74 20 74 6f 20 74 68 69 73 20 73  yright to this s
0040: 6f 75 72 63 65 20 63 6f 64 65 2e 20 20 49 6e 20  ource code.  In 
0050: 70 6c 61 63 65 20 6f 66 0a 23 20 61 20 6c 65 67  place of.# a leg
0060: 61 6c 20 6e 6f 74 69 63 65 2c 20 68 65 72 65 20  al notice, here 
0070: 69 73 20 61 20 62 6c 65 73 73 69 6e 67 3a 0a 23  is a blessing:.#
0080: 0a 23 20 20 20 20 4d 61 79 20 79 6f 75 20 64 6f  .#    May you do
0090: 20 67 6f 6f 64 20 61 6e 64 20 6e 6f 74 20 65 76   good and not ev
00a0: 69 6c 2e 0a 23 20 20 20 20 4d 61 79 20 79 6f 75  il..#    May you
00b0: 20 66 69 6e 64 20 66 6f 72 67 69 76 65 6e 65 73   find forgivenes
00c0: 73 20 66 6f 72 20 79 6f 75 72 73 65 6c 66 20 61  s for yourself a
00d0: 6e 64 20 66 6f 72 67 69 76 65 20 6f 74 68 65 72  nd forgive other
00e0: 73 2e 0a 23 20 20 20 20 4d 61 79 20 79 6f 75 20  s..#    May you 
00f0: 73 68 61 72 65 20 66 72 65 65 6c 79 2c 20 6e 65  share freely, ne
0100: 76 65 72 20 74 61 6b 69 6e 67 20 6d 6f 72 65 20  ver taking more 
0110: 74 68 61 6e 20 79 6f 75 20 67 69 76 65 2e 0a 23  than you give..#
0120: 0a 23 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  .#**************
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 23 0a 23 20 54 68  *********.#.# Th
0170: 69 73 20 66 69 6c 65 20 69 6d 70 6c 65 6d 65 6e  is file implemen
0180: 74 73 20 74 65 73 74 73 20 74 6f 20 76 65 72 69  ts tests to veri
0190: 66 79 20 74 68 61 74 20 74 68 65 20 22 74 65 73  fy that the "tes
01a0: 74 61 62 6c 65 20 73 74 61 74 65 6d 65 6e 74 73  table statements
01b0: 22 20 69 6e 20 0a 23 20 74 68 65 20 6c 61 6e 67  " in .# the lang
01c0: 5f 73 65 6c 65 63 74 2e 68 74 6d 6c 20 64 6f 63  _select.html doc
01d0: 75 6d 65 6e 74 20 61 72 65 20 63 6f 72 72 65 63  ument are correc
01e0: 74 2e 0a 23 0a 0a 73 65 74 20 74 65 73 74 64 69  t..#..set testdi
01f0: 72 20 5b 66 69 6c 65 20 64 69 72 6e 61 6d 65 20  r [file dirname 
0200: 24 61 72 67 76 30 5d 0a 73 6f 75 72 63 65 20 24  $argv0].source $
0210: 74 65 73 74 64 69 72 2f 74 65 73 74 65 72 2e 74  testdir/tester.t
0220: 63 6c 0a 0a 23 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  cl..#-----------
0230: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
0240: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
0250: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
0260: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 0a 23  --------------.#
0270: 20 74 65 5f 2a 20 63 6f 6d 6d 61 6e 64 73 3a 0a   te_* commands:.
0280: 23 0a 23 0a 23 20 20 20 74 65 5f 72 65 61 64 5f  #.#.#   te_read_
0290: 73 71 6c 20 44 42 20 53 45 4c 45 43 54 2d 53 54  sql DB SELECT-ST
02a0: 41 54 45 4d 45 4e 54 0a 23 20 20 20 74 65 5f 72  ATEMENT.#   te_r
02b0: 65 61 64 5f 74 62 6c 20 44 42 20 54 41 42 4c 45  ead_tbl DB TABLE
02c0: 4e 41 4d 45 0a 23 0a 23 20 54 68 65 73 65 20 74  NAME.#.# These t
02d0: 77 6f 20 63 6f 6d 6d 61 6e 64 73 20 61 72 65 20  wo commands are 
02e0: 75 73 65 64 20 74 6f 20 72 65 61 64 20 61 20 64  used to read a d
02f0: 61 74 61 73 65 74 20 66 72 6f 6d 20 74 68 65 20  ataset from the 
0300: 64 61 74 61 62 61 73 65 2e 20 41 20 64 61 74 61  database. A data
0310: 73 65 74 0a 23 20 63 6f 6e 73 69 73 74 73 20 6f  set.# consists o
0320: 66 20 4e 20 72 6f 77 73 20 6f 66 20 4d 20 6e 61  f N rows of M na
0330: 6d 65 64 20 63 6f 6c 75 6d 6e 73 20 6f 66 20 76  med columns of v
0340: 61 6c 75 65 73 20 65 61 63 68 2c 20 77 68 65 72  alues each, wher
0350: 65 20 65 61 63 68 20 76 61 6c 75 65 20 68 61 73  e each value has
0360: 20 61 0a 23 20 74 79 70 65 20 28 6e 75 6c 6c 2c   a.# type (null,
0370: 20 69 6e 74 65 67 65 72 2c 20 72 65 61 6c 2c 20   integer, real, 
0380: 74 65 78 74 20 6f 72 20 62 6c 6f 62 29 20 61 6e  text or blob) an
0390: 64 20 61 20 76 61 6c 75 65 20 77 69 74 68 69 6e  d a value within
03a0: 20 74 68 65 20 74 79 70 65 73 20 64 6f 6d 61 69   the types domai
03b0: 6e 2e 0a 23 20 54 68 65 20 74 63 6c 20 66 6f 72  n..# The tcl for
03c0: 6d 61 74 20 66 6f 72 20 61 20 22 64 61 74 61 73  mat for a "datas
03d0: 65 74 22 20 69 73 20 61 20 6c 69 73 74 20 6f 66  et" is a list of
03e0: 20 74 77 6f 20 65 6c 65 6d 65 6e 74 73 3a 0a 23   two elements:.#
03f0: 0a 23 20 20 20 2a 20 41 20 6c 69 73 74 20 6f 66  .#   * A list of
0400: 20 74 68 65 20 63 6f 6c 75 6d 6e 20 6e 61 6d 65   the column name
0410: 73 2e 0a 23 20 20 20 2a 20 41 20 6c 69 73 74 20  s..#   * A list 
0420: 6f 66 20 64 61 74 61 20 72 6f 77 73 2e 20 45 61  of data rows. Ea
0430: 63 68 20 72 6f 77 20 69 73 20 69 74 73 65 6c 66  ch row is itself
0440: 20 61 20 6c 69 73 74 2c 20 77 68 65 72 65 20 65   a list, where e
0450: 61 63 68 20 65 6c 65 6d 65 6e 74 20 69 73 0a 23  ach element is.#
0460: 20 20 20 20 20 74 68 65 20 63 6f 6e 74 65 6e 74       the content
0470: 73 20 6f 66 20 61 20 63 6f 6c 75 6d 6e 20 6f 66  s of a column of
0480: 20 74 68 65 20 72 6f 77 2e 20 45 61 63 68 20 6f   the row. Each o
0490: 66 20 74 68 65 73 65 20 69 73 20 61 20 6c 69 73  f these is a lis
04a0: 74 20 6f 66 20 74 77 6f 0a 23 20 20 20 20 20 65  t of two.#     e
04b0: 6c 65 6d 65 6e 74 73 2c 20 74 68 65 20 74 79 70  lements, the typ
04c0: 65 20 6e 61 6d 65 20 61 6e 64 20 74 68 65 20 61  e name and the a
04d0: 63 74 75 61 6c 20 76 61 6c 75 65 2e 0a 23 0a 23  ctual value..#.#
04e0: 20 46 6f 72 20 65 78 61 6d 70 6c 65 2c 20 74 68   For example, th
04f0: 65 20 63 6f 6e 74 65 6e 74 73 20 6f 66 20 74 61  e contents of ta
0500: 62 6c 65 20 5b 74 31 5d 20 61 73 20 61 20 64 61  ble [t1] as a da
0510: 74 61 73 65 74 20 69 73 3a 0a 23 0a 23 20 20 20  taset is:.#.#   
0520: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 31 28  CREATE TABLE t1(
0530: 61 2c 20 62 29 3b 0a 23 20 20 20 49 4e 53 45 52  a, b);.#   INSER
0540: 54 20 49 4e 54 4f 20 74 31 20 56 41 4c 55 45 53  T INTO t1 VALUES
0550: 28 27 61 62 63 27 2c 20 4e 55 4c 4c 29 3b 0a 23  ('abc', NULL);.#
0560: 20 20 20 49 4e 53 45 52 54 20 49 4e 54 4f 20 74     INSERT INTO t
0570: 31 20 56 41 4c 55 45 53 28 34 33 2e 31 2c 20 32  1 VALUES(43.1, 2
0580: 32 29 3b 0a 23 0a 23 20 20 20 7b 61 20 62 7d 20  2);.#.#   {a b} 
0590: 7b 7b 7b 54 45 58 54 20 61 62 63 7d 20 7b 4e 55  {{{TEXT abc} {NU
05a0: 4c 4c 20 7b 7d 7d 7d 20 7b 7b 52 45 41 4c 20 34  LL {}}} {{REAL 4
05b0: 33 2e 31 7d 20 7b 49 4e 54 45 47 45 52 20 32 32  3.1} {INTEGER 22
05c0: 7d 7d 7d 0a 23 0a 23 20 54 68 65 20 5b 74 65 5f  }}}.#.# The [te_
05d0: 72 65 61 64 5f 74 62 6c 5d 20 63 6f 6d 6d 61 6e  read_tbl] comman
05e0: 64 20 72 65 74 75 72 6e 73 20 61 20 64 61 74 61  d returns a data
05f0: 73 65 74 20 72 65 61 64 20 66 72 6f 6d 20 61 20  set read from a 
0600: 74 61 62 6c 65 2e 20 54 68 65 0a 23 20 5b 74 65  table. The.# [te
0610: 5f 72 65 61 64 5f 73 71 6c 5d 20 72 65 74 75 72  _read_sql] retur
0620: 6e 73 20 74 68 65 20 64 61 74 61 73 65 74 20 74  ns the dataset t
0630: 68 61 74 20 72 65 73 75 6c 74 73 20 66 72 6f 6d  hat results from
0640: 20 65 78 65 63 75 74 69 6e 67 20 61 20 53 45 4c   executing a SEL
0650: 45 43 54 0a 23 20 63 6f 6d 6d 61 6e 64 2e 0a 23  ECT.# command..#
0660: 0a 23 0a 23 20 20 20 74 65 5f 74 62 6c 6a 6f 69  .#.#   te_tbljoi
0670: 6e 20 3f 53 57 49 54 43 48 45 53 3f 20 4c 48 53  n ?SWITCHES? LHS
0680: 2d 54 41 42 4c 45 20 52 48 53 2d 54 41 42 4c 45  -TABLE RHS-TABLE
0690: 0a 23 20 20 20 74 65 5f 6a 6f 69 6e 20 3f 53 57  .#   te_join ?SW
06a0: 49 54 43 48 45 53 3f 20 4c 48 53 2d 44 41 54 41  ITCHES? LHS-DATA
06b0: 53 45 54 20 52 48 53 2d 44 41 54 41 53 45 54 0a  SET RHS-DATASET.
06c0: 23 0a 23 20 54 68 69 73 20 63 6f 6d 6d 61 6e 64  #.# This command
06d0: 20 6a 6f 69 6e 73 20 74 68 65 20 74 77 6f 20 64   joins the two d
06e0: 61 74 61 73 65 74 73 20 61 6e 64 20 72 65 74 75  atasets and retu
06f0: 72 6e 73 20 74 68 65 20 72 65 73 75 6c 74 69 6e  rns the resultin
0700: 67 20 64 61 74 61 73 65 74 2e 20 49 66 20 0a 23  g dataset. If .#
0710: 20 74 68 65 72 65 20 61 72 65 20 6e 6f 20 73 77   there are no sw
0720: 69 74 63 68 65 73 20 73 70 65 63 69 66 69 65 64  itches specified
0730: 2c 20 74 68 65 6e 20 74 68 65 20 72 65 73 75 6c  , then the resul
0740: 74 73 20 69 73 20 74 68 65 20 63 61 72 74 65 73  ts is the cartes
0750: 69 61 6e 20 70 72 6f 64 75 63 74 0a 23 20 6f 66  ian product.# of
0760: 20 74 68 65 20 74 77 6f 20 69 6e 70 75 74 73 2e   the two inputs.
0770: 20 20 54 68 65 20 5b 74 65 5f 74 62 6c 6a 6f 69    The [te_tbljoi
0780: 6e 5d 20 63 6f 6d 6d 61 6e 64 20 72 65 61 64 73  n] command reads
0790: 20 74 68 65 20 6c 65 66 74 20 61 6e 64 20 72 69   the left and ri
07a0: 67 68 74 2d 68 61 6e 64 0a 23 20 64 61 74 61 73  ght-hand.# datas
07b0: 65 74 73 20 66 72 6f 6d 20 74 68 65 20 73 70 65  ets from the spe
07c0: 63 69 66 69 65 64 20 74 61 62 6c 65 73 2e 20 54  cified tables. T
07d0: 68 65 20 5b 74 65 5f 6a 6f 69 6e 5d 20 63 6f 6d  he [te_join] com
07e0: 6d 61 6e 64 20 69 73 20 70 61 73 73 65 64 20 74  mand is passed t
07f0: 68 65 0a 23 20 64 61 74 61 73 65 74 73 20 64 69  he.# datasets di
0800: 72 65 63 74 6c 79 2e 0a 23 0a 23 20 4f 70 74 69  rectly..#.# Opti
0810: 6f 6e 61 6c 20 73 77 69 74 63 68 65 73 20 61 72  onal switches ar
0820: 65 20 61 73 20 66 6f 6c 6c 6f 77 73 3a 0a 23 0a  e as follows:.#.
0830: 23 20 20 20 2d 6f 6e 20 53 43 52 49 50 54 0a 23  #   -on SCRIPT.#
0840: 20 20 20 2d 75 73 69 6e 67 20 43 4f 4c 55 4d 4e     -using COLUMN
0850: 2d 4c 49 53 54 0a 23 20 20 20 2d 6c 65 66 74 0a  -LIST.#   -left.
0860: 23 0a 23 20 54 68 65 20 2d 6f 6e 20 6f 70 74 69  #.# The -on opti
0870: 6f 6e 20 73 70 65 63 69 66 69 65 73 20 61 20 74  on specifies a t
0880: 63 6c 20 73 63 72 69 70 74 20 74 68 61 74 20 69  cl script that i
0890: 73 20 65 78 65 63 75 74 65 64 20 66 6f 72 20 65  s executed for e
08a0: 61 63 68 20 72 6f 77 20 69 6e 20 74 68 65 0a 23  ach row in the.#
08b0: 20 63 61 72 74 65 73 69 61 6e 20 70 72 6f 64 75   cartesian produ
08c0: 63 74 20 6f 66 20 74 68 65 20 74 77 6f 20 64 61  ct of the two da
08d0: 74 61 73 65 74 73 2e 20 54 68 65 20 73 63 72 69  tasets. The scri
08e0: 70 74 20 68 61 73 20 34 20 61 72 67 75 6d 65 6e  pt has 4 argumen
08f0: 74 73 20 61 70 70 65 6e 64 65 64 0a 23 20 74 6f  ts appended.# to
0900: 20 69 74 2c 20 69 6e 20 74 68 65 20 66 6f 6c 6c   it, in the foll
0910: 6f 77 69 6e 67 20 6f 72 64 65 72 3a 0a 23 0a 23  owing order:.#.#
0920: 20 20 20 2a 20 54 68 65 20 6c 69 73 74 20 6f 66     * The list of
0930: 20 63 6f 6c 75 6d 6e 2d 6e 61 6d 65 73 20 66 72   column-names fr
0940: 6f 6d 20 74 68 65 20 6c 65 66 74 2d 68 61 6e 64  om the left-hand
0950: 20 64 61 74 61 73 65 74 2e 0a 23 20 20 20 2a 20   dataset..#   * 
0960: 41 20 73 69 6e 67 6c 65 20 72 6f 77 20 66 72 6f  A single row fro
0970: 6d 20 74 68 65 20 6c 65 66 74 2d 68 61 6e 64 20  m the left-hand 
0980: 64 61 74 61 73 65 74 20 28 6f 6e 65 20 22 64 61  dataset (one "da
0990: 74 61 20 72 6f 77 22 20 6c 69 73 74 20 61 73 20  ta row" list as 
09a0: 0a 23 20 20 20 20 20 64 65 73 63 72 69 62 65 64  .#     described
09b0: 20 61 62 6f 76 65 2e 0a 23 20 20 20 2a 20 54 68   above..#   * Th
09c0: 65 20 6c 69 73 74 20 6f 66 20 63 6f 6c 75 6d 6e  e list of column
09d0: 2d 6e 61 6d 65 73 20 66 72 6f 6d 20 74 68 65 20  -names from the 
09e0: 72 69 67 68 74 2d 68 61 6e 64 20 64 61 74 61 73  right-hand datas
09f0: 65 74 2e 0a 23 20 20 20 2a 20 41 20 73 69 6e 67  et..#   * A sing
0a00: 6c 65 20 72 6f 77 20 66 72 6f 6d 20 74 68 65 20  le row from the 
0a10: 72 69 67 68 74 2d 68 61 6e 64 20 64 61 74 61 73  right-hand datas
0a20: 65 74 2e 0a 23 0a 23 20 54 68 65 20 73 63 72 69  et..#.# The scri
0a30: 70 74 20 6d 75 73 74 20 72 65 74 75 72 6e 20 61  pt must return a
0a40: 20 62 6f 6f 6c 65 61 6e 20 76 61 6c 75 65 20 2d   boolean value -
0a50: 20 74 72 75 65 20 69 66 20 74 68 65 20 63 6f 6d   true if the com
0a60: 62 69 6e 61 74 69 6f 6e 20 6f 66 20 72 6f 77 73  bination of rows
0a70: 0a 23 20 73 68 6f 75 6c 64 20 62 65 20 69 6e 63  .# should be inc
0a80: 6c 75 64 65 64 20 69 6e 20 74 68 65 20 6f 75 74  luded in the out
0a90: 70 75 74 20 64 61 74 61 73 65 74 2c 20 6f 72 20  put dataset, or 
0aa0: 66 61 6c 73 65 20 6f 74 68 65 72 77 69 73 65 2e  false otherwise.
0ab0: 0a 23 0a 23 20 54 68 65 20 2d 75 73 69 6e 67 20  .#.# The -using 
0ac0: 6f 70 74 69 6f 6e 20 73 70 65 63 69 66 69 65 73  option specifies
0ad0: 20 61 20 6c 69 73 74 20 6f 66 20 74 68 65 20 63   a list of the c
0ae0: 6f 6c 75 6d 6e 73 20 66 72 6f 6d 20 74 68 65 20  olumns from the 
0af0: 72 69 67 68 74 2d 68 61 6e 64 0a 23 20 64 61 74  right-hand.# dat
0b00: 61 73 65 74 20 74 68 61 74 20 73 68 6f 75 6c 64  aset that should
0b10: 20 62 65 20 6f 6d 69 74 74 65 64 20 66 72 6f 6d   be omitted from
0b20: 20 74 68 65 20 6f 75 74 70 75 74 20 64 61 74 61   the output data
0b30: 73 65 74 2e 0a 23 0a 23 20 49 66 20 74 68 65 20  set..#.# If the 
0b40: 2d 6c 65 66 74 20 6f 70 74 69 6f 6e 20 69 73 20  -left option is 
0b50: 70 72 65 73 65 6e 74 2c 20 74 68 65 20 6a 6f 69  present, the joi
0b60: 6e 20 69 73 20 64 6f 6e 65 20 4c 45 46 54 20 4a  n is done LEFT J
0b70: 4f 49 4e 20 73 74 79 6c 65 2e 20 0a 23 20 53 70  OIN style. .# Sp
0b80: 65 63 69 66 69 63 61 6c 6c 79 2c 20 61 6e 20 65  ecifically, an e
0b90: 78 74 72 61 20 72 6f 77 20 69 73 20 69 6e 73 65  xtra row is inse
0ba0: 72 74 65 64 20 69 66 20 61 66 74 65 72 20 74 68  rted if after th
0bb0: 65 20 2d 6f 6e 20 73 63 72 69 70 74 20 69 73 20  e -on script is 
0bc0: 72 75 6e 20 74 68 65 72 65 0a 23 20 65 78 69 73  run there.# exis
0bd0: 74 20 72 6f 77 73 20 69 6e 20 74 68 65 20 6c 65  t rows in the le
0be0: 66 74 2d 68 61 6e 64 20 64 61 74 61 73 65 74 20  ft-hand dataset 
0bf0: 74 68 61 74 20 68 61 76 65 20 6e 6f 20 63 6f 72  that have no cor
0c00: 72 65 73 70 6f 6e 64 69 6e 67 20 72 6f 77 73 20  responding rows 
0c10: 69 6e 0a 23 20 74 68 65 20 6f 75 74 70 75 74 2e  in.# the output.
0c20: 20 53 65 65 20 74 68 65 20 69 6d 70 6c 65 6d 65   See the impleme
0c30: 6e 74 61 74 69 6f 6e 20 66 6f 72 20 6d 6f 72 65  ntation for more
0c40: 20 73 70 65 63 69 66 69 63 20 63 6f 6d 6d 65 6e   specific commen
0c50: 74 73 2e 0a 23 0a 23 0a 23 20 20 20 74 65 5f 65  ts..#.#.#   te_e
0c60: 71 75 61 6c 73 20 3f 53 57 49 54 43 48 45 53 3f  quals ?SWITCHES?
0c70: 20 43 4f 4c 4e 41 4d 45 31 20 43 4f 4c 4e 41 4d   COLNAME1 COLNAM
0c80: 45 32 20 3c 2d 6f 6e 20 73 63 72 69 70 74 20 61  E2 <-on script a
0c90: 72 67 73 3e 0a 23 0a 23 20 54 68 65 20 6f 6e 6c  rgs>.#.# The onl
0ca0: 79 20 73 75 70 70 6f 72 74 65 64 20 73 77 69 74  y supported swit
0cb0: 63 68 20 69 73 20 22 2d 6e 6f 63 61 73 65 22 2e  ch is "-nocase".
0cc0: 20 49 66 20 69 74 20 69 73 20 70 72 65 73 65 6e   If it is presen
0cd0: 74 2c 20 74 68 65 6e 20 74 65 78 74 20 76 61 6c  t, then text val
0ce0: 75 65 73 0a 23 20 61 72 65 20 63 6f 6d 70 61 72  ues.# are compar
0cf0: 65 64 20 69 6e 20 61 20 63 61 73 65 2d 69 6e 64  ed in a case-ind
0d00: 65 70 65 6e 64 65 6e 74 20 66 61 73 68 69 6f 6e  ependent fashion
0d10: 2e 20 4f 74 68 65 72 77 69 73 65 2c 20 74 68 65  . Otherwise, the
0d20: 79 20 61 72 65 20 63 6f 6d 70 61 72 65 64 0a 23  y are compared.#
0d30: 20 61 73 20 69 66 20 75 73 69 6e 67 20 74 68 65   as if using the
0d40: 20 53 51 4c 69 74 65 20 42 49 4e 41 52 59 20 63   SQLite BINARY c
0d50: 6f 6c 6c 61 74 69 6f 6e 20 73 65 71 75 65 6e 63  ollation sequenc
0d60: 65 2e 0a 23 0a 23 0a 23 20 20 20 74 65 5f 61 6e  e..#.#.#   te_an
0d70: 64 20 4f 4e 53 43 52 49 50 54 31 20 4f 4e 53 43  d ONSCRIPT1 ONSC
0d80: 52 49 50 54 32 2e 2e 2e 0a 23 0a 23 0a 0a 0a 23  RIPT2....#.#...#
0d90: 0a 23 20 20 20 74 65 5f 72 65 61 64 5f 74 62 6c  .#   te_read_tbl
0da0: 20 44 42 20 54 41 42 4c 45 4e 41 4d 45 0a 23 20   DB TABLENAME.# 
0db0: 20 20 74 65 5f 72 65 61 64 5f 73 71 6c 20 44 42    te_read_sql DB
0dc0: 20 53 45 4c 45 43 54 2d 53 54 41 54 45 4d 45 4e   SELECT-STATEMEN
0dd0: 54 0a 23 0a 23 20 54 68 65 73 65 20 74 77 6f 20  T.#.# These two 
0de0: 70 72 6f 63 73 20 61 72 65 20 75 73 65 64 20 74  procs are used t
0df0: 6f 20 65 78 74 72 61 63 74 20 64 61 74 61 73 65  o extract datase
0e00: 74 73 20 66 72 6f 6d 20 74 68 65 20 64 61 74 61  ts from the data
0e10: 62 61 73 65 2c 20 65 69 74 68 65 72 0a 23 20 62  base, either.# b
0e20: 79 20 72 65 61 64 69 6e 67 20 74 68 65 20 63 6f  y reading the co
0e30: 6e 74 65 6e 74 73 20 6f 66 20 61 20 6e 61 6d 65  ntents of a name
0e40: 64 20 74 61 62 6c 65 20 28 74 65 5f 72 65 61 64  d table (te_read
0e50: 5f 74 62 6c 29 2c 20 6f 72 20 62 79 20 65 78 65  _tbl), or by exe
0e60: 63 75 74 69 6e 67 0a 23 20 61 20 53 45 4c 45 43  cuting.# a SELEC
0e70: 54 20 73 74 61 74 65 6d 65 6e 74 20 28 74 33 5f  T statement (t3_
0e80: 72 65 61 64 5f 73 71 6c 29 2e 20 20 0a 23 0a 23  read_sql).  .#.#
0e90: 20 53 65 65 20 74 68 65 20 63 6f 6d 6d 65 6e 74   See the comment
0ea0: 20 61 62 6f 76 65 2c 20 64 65 73 63 72 69 62 69   above, describi
0eb0: 6e 67 20 22 74 65 5f 2a 20 63 6f 6d 6d 61 6e 64  ng "te_* command
0ec0: 73 22 2c 20 66 6f 72 20 64 65 74 61 69 6c 73 20  s", for details 
0ed0: 6f 66 20 74 68 65 0a 23 20 72 65 74 75 72 6e 20  of the.# return 
0ee0: 76 61 6c 75 65 73 2e 0a 23 0a 70 72 6f 63 20 74  values..#.proc t
0ef0: 65 5f 72 65 61 64 5f 74 62 6c 20 7b 64 62 20 74  e_read_tbl {db t
0f00: 62 6c 7d 20 7b 0a 20 74 65 5f 72 65 61 64 5f 73  bl} {. te_read_s
0f10: 71 6c 20 24 64 62 20 22 53 45 4c 45 43 54 20 2a  ql $db "SELECT *
0f20: 20 46 52 4f 4d 20 27 24 74 62 6c 27 22 0a 7d 0a   FROM '$tbl'".}.
0f30: 70 72 6f 63 20 74 65 5f 72 65 61 64 5f 73 71 6c  proc te_read_sql
0f40: 20 7b 64 62 20 73 71 6c 7d 20 7b 0a 20 20 73 65   {db sql} {.  se
0f50: 74 20 53 20 5b 73 71 6c 69 74 65 33 5f 70 72 65  t S [sqlite3_pre
0f60: 70 61 72 65 5f 76 32 20 24 64 62 20 24 73 71 6c  pare_v2 $db $sql
0f70: 20 2d 31 20 44 55 4d 4d 59 5d 0a 0a 20 20 73 65   -1 DUMMY]..  se
0f80: 74 20 63 6f 6c 73 20 5b 6c 69 73 74 5d 0a 20 20  t cols [list].  
0f90: 66 6f 72 20 7b 73 65 74 20 69 20 30 7d 20 7b 24  for {set i 0} {$
0fa0: 69 20 3c 20 5b 73 71 6c 69 74 65 33 5f 63 6f 6c  i < [sqlite3_col
0fb0: 75 6d 6e 5f 63 6f 75 6e 74 20 24 53 5d 7d 20 7b  umn_count $S]} {
0fc0: 69 6e 63 72 20 69 7d 20 7b 0a 20 20 20 20 6c 61  incr i} {.    la
0fd0: 70 70 65 6e 64 20 63 6f 6c 73 20 5b 73 71 6c 69  ppend cols [sqli
0fe0: 74 65 33 5f 63 6f 6c 75 6d 6e 5f 6e 61 6d 65 20  te3_column_name 
0ff0: 24 53 20 24 69 5d 0a 20 20 7d 0a 0a 20 20 73 65  $S $i].  }..  se
1000: 74 20 72 6f 77 73 20 5b 6c 69 73 74 5d 0a 20 20  t rows [list].  
1010: 77 68 69 6c 65 20 7b 5b 73 71 6c 69 74 65 33 5f  while {[sqlite3_
1020: 73 74 65 70 20 24 53 5d 20 3d 3d 20 22 53 51 4c  step $S] == "SQL
1030: 49 54 45 5f 52 4f 57 22 7d 20 7b 0a 20 20 20 20  ITE_ROW"} {.    
1040: 73 65 74 20 72 20 5b 6c 69 73 74 5d 0a 20 20 20  set r [list].   
1050: 20 66 6f 72 20 7b 73 65 74 20 69 20 30 7d 20 7b   for {set i 0} {
1060: 24 69 20 3c 20 5b 73 71 6c 69 74 65 33 5f 63 6f  $i < [sqlite3_co
1070: 6c 75 6d 6e 5f 63 6f 75 6e 74 20 24 53 5d 7d 20  lumn_count $S]} 
1080: 7b 69 6e 63 72 20 69 7d 20 7b 0a 20 20 20 20 20  {incr i} {.     
1090: 20 6c 61 70 70 65 6e 64 20 72 20 5b 6c 69 73 74   lappend r [list
10a0: 20 5b 73 71 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e   [sqlite3_column
10b0: 5f 74 79 70 65 20 24 53 20 24 69 5d 20 5b 73 71  _type $S $i] [sq
10c0: 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f 74 65 78  lite3_column_tex
10d0: 74 20 24 53 20 24 69 5d 5d 0a 20 20 20 20 7d 0a  t $S $i]].    }.
10e0: 20 20 20 20 6c 61 70 70 65 6e 64 20 72 6f 77 73      lappend rows
10f0: 20 24 72 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65   $r.  }.  sqlite
1100: 33 5f 66 69 6e 61 6c 69 7a 65 20 24 53 0a 0a 20  3_finalize $S.. 
1110: 20 72 65 74 75 72 6e 20 5b 6c 69 73 74 20 24 63   return [list $c
1120: 6f 6c 73 20 24 72 6f 77 73 5d 0a 7d 0a 0a 23 2d  ols $rows].}..#-
1130: 2d 2d 2d 2d 2d 2d 0a 23 20 55 73 61 67 65 3a 20  ------.# Usage: 
1140: 20 20 74 65 5f 6a 6f 69 6e 20 3c 74 61 62 6c 65    te_join <table
1150: 2d 64 61 74 61 31 3e 20 3c 74 61 62 6c 65 2d 64  -data1> <table-d
1160: 61 74 61 32 3e 20 3c 6a 6f 69 6e 20 73 70 65 63  ata2> <join spec
1170: 3e 2e 2e 2e 0a 23 0a 23 20 57 68 65 72 65 20 61  >....#.# Where a
1180: 20 6a 6f 69 6e 2d 73 70 65 63 20 69 73 20 61 6e   join-spec is an
1190: 20 6f 70 74 69 6f 6e 61 6c 20 6c 69 73 74 20 6f   optional list o
11a0: 66 20 61 72 67 75 6d 65 6e 74 73 20 61 73 20 66  f arguments as f
11b0: 6f 6c 6c 6f 77 73 3a 0a 23 0a 23 20 20 20 3f 2d  ollows:.#.#   ?-
11c0: 6c 65 66 74 3f 0a 23 20 20 20 3f 2d 75 73 69 6e  left?.#   ?-usin
11d0: 67 20 63 6f 6c 6e 61 6d 65 2d 6c 69 73 74 3f 0a  g colname-list?.
11e0: 23 20 20 20 3f 2d 6f 6e 20 6f 6e 2d 65 78 70 72  #   ?-on on-expr
11f0: 2d 70 72 6f 63 3f 0a 23 0a 70 72 6f 63 20 74 65  -proc?.#.proc te
1200: 5f 6a 6f 69 6e 20 7b 64 61 74 61 31 20 64 61 74  _join {data1 dat
1210: 61 32 20 61 72 67 73 7d 20 7b 0a 0a 20 20 73 65  a2 args} {..  se
1220: 74 20 74 65 73 74 70 72 6f 63 20 22 22 0a 20 20  t testproc "".  
1230: 73 65 74 20 75 73 69 6e 67 6c 69 73 74 20 5b 6c  set usinglist [l
1240: 69 73 74 5d 0a 20 20 73 65 74 20 69 73 6c 65 66  ist].  set islef
1250: 74 20 30 0a 20 20 66 6f 72 20 7b 73 65 74 20 69  t 0.  for {set i
1260: 20 30 7d 20 7b 24 69 20 3c 20 5b 6c 6c 65 6e 67   0} {$i < [lleng
1270: 74 68 20 24 61 72 67 73 5d 7d 20 7b 69 6e 63 72  th $args]} {incr
1280: 20 69 7d 20 7b 0a 20 20 20 20 73 65 74 20 61 20   i} {.    set a 
1290: 5b 6c 69 6e 64 65 78 20 24 61 72 67 73 20 24 69  [lindex $args $i
12a0: 5d 0a 20 20 20 20 73 77 69 74 63 68 20 2d 2d 20  ].    switch -- 
12b0: 24 61 20 7b 0a 20 20 20 20 20 20 2d 6f 6e 20 20  $a {.      -on  
12c0: 20 20 20 7b 20 73 65 74 20 74 65 73 74 70 72 6f     { set testpro
12d0: 63 20 5b 6c 69 6e 64 65 78 20 24 61 72 67 73 20  c [lindex $args 
12e0: 5b 69 6e 63 72 20 69 5d 5d 20 7d 0a 20 20 20 20  [incr i]] }.    
12f0: 20 20 2d 75 73 69 6e 67 20 20 7b 20 73 65 74 20    -using  { set 
1300: 75 73 69 6e 67 6c 69 73 74 20 5b 6c 69 6e 64 65  usinglist [linde
1310: 78 20 24 61 72 67 73 20 5b 69 6e 63 72 20 69 5d  x $args [incr i]
1320: 5d 20 7d 0a 20 20 20 20 20 20 2d 6c 65 66 74 20  ] }.      -left 
1330: 20 20 7b 20 73 65 74 20 69 73 6c 65 66 74 20 31    { set isleft 1
1340: 20 7d 0a 20 20 20 20 20 20 64 65 66 61 75 6c 74   }.      default
1350: 20 7b 0a 20 20 20 20 20 20 20 20 65 72 72 6f 72   {.        error
1360: 20 22 55 6e 6b 6e 6f 77 6e 20 61 72 67 75 6d 65   "Unknown argume
1370: 6e 74 3a 20 24 61 22 0a 20 20 20 20 20 20 7d 0a  nt: $a".      }.
1380: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 73 65 74      }.  }..  set
1390: 20 63 31 20 5b 6c 69 6e 64 65 78 20 24 64 61 74   c1 [lindex $dat
13a0: 61 31 20 30 5d 0a 20 20 73 65 74 20 63 32 20 5b  a1 0].  set c2 [
13b0: 6c 69 6e 64 65 78 20 24 64 61 74 61 32 20 30 5d  lindex $data2 0]
13c0: 0a 20 20 73 65 74 20 6f 6d 69 74 6c 69 73 74 20  .  set omitlist 
13d0: 5b 6c 69 73 74 5d 0a 20 20 73 65 74 20 6e 75 6c  [list].  set nul
13e0: 6c 72 6f 77 6c 69 73 74 20 5b 6c 69 73 74 5d 0a  lrowlist [list].
13f0: 20 20 73 65 74 20 63 72 65 74 20 24 63 31 0a 0a    set cret $c1..
1400: 20 20 73 65 74 20 63 69 64 78 20 30 0a 20 20 66    set cidx 0.  f
1410: 6f 72 65 61 63 68 20 63 6f 6c 20 24 63 32 20 7b  oreach col $c2 {
1420: 0a 20 20 20 20 73 65 74 20 69 64 78 20 5b 6c 73  .    set idx [ls
1430: 65 61 72 63 68 20 24 75 73 69 6e 67 6c 69 73 74  earch $usinglist
1440: 20 24 63 6f 6c 5d 0a 20 20 20 20 69 66 20 7b 24   $col].    if {$
1450: 69 64 78 3e 3d 30 7d 20 7b 6c 61 70 70 65 6e 64  idx>=0} {lappend
1460: 20 6f 6d 69 74 6c 69 73 74 20 24 63 69 64 78 7d   omitlist $cidx}
1470: 0a 20 20 20 20 69 66 20 7b 24 69 64 78 3c 30 7d  .    if {$idx<0}
1480: 20 7b 0a 20 20 20 20 20 20 6c 61 70 70 65 6e 64   {.      lappend
1490: 20 6e 75 6c 6c 72 6f 77 6c 69 73 74 20 7b 4e 55   nullrowlist {NU
14a0: 4c 4c 20 7b 7d 7d 0a 20 20 20 20 20 20 6c 61 70  LL {}}.      lap
14b0: 70 65 6e 64 20 63 72 65 74 20 24 63 6f 6c 0a 20  pend cret $col. 
14c0: 20 20 20 7d 0a 20 20 20 20 69 6e 63 72 20 63 69     }.    incr ci
14d0: 64 78 0a 20 20 7d 0a 20 20 73 65 74 20 6f 6d 69  dx.  }.  set omi
14e0: 74 6c 69 73 74 20 5b 6c 73 6f 72 74 20 2d 69 6e  tlist [lsort -in
14f0: 74 65 67 65 72 20 2d 64 65 63 72 65 61 73 69 6e  teger -decreasin
1500: 67 20 24 6f 6d 69 74 6c 69 73 74 5d 0a 0a 0a 20  g $omitlist]... 
1510: 20 73 65 74 20 72 72 65 74 20 5b 6c 69 73 74 5d   set rret [list]
1520: 0a 20 20 66 6f 72 65 61 63 68 20 72 31 20 5b 6c  .  foreach r1 [l
1530: 69 6e 64 65 78 20 24 64 61 74 61 31 20 31 5d 20  index $data1 1] 
1540: 7b 0a 20 20 20 20 73 65 74 20 6f 6e 65 20 30 0a  {.    set one 0.
1550: 20 20 20 20 66 6f 72 65 61 63 68 20 72 32 20 5b      foreach r2 [
1560: 6c 69 6e 64 65 78 20 24 64 61 74 61 32 20 31 5d  lindex $data2 1]
1570: 20 7b 0a 20 20 20 20 20 20 73 65 74 20 6f 6b 20   {.      set ok 
1580: 31 0a 20 20 20 20 20 20 69 66 20 7b 24 74 65 73  1.      if {$tes
1590: 74 70 72 6f 63 20 21 3d 20 22 22 7d 20 7b 0a 20  tproc != ""} {. 
15a0: 20 20 20 20 20 20 20 73 65 74 20 6f 6b 20 5b 65         set ok [e
15b0: 76 61 6c 20 24 74 65 73 74 70 72 6f 63 20 5b 6c  val $testproc [l
15c0: 69 73 74 20 24 63 31 20 24 72 31 20 24 63 32 20  ist $c1 $r1 $c2 
15d0: 24 72 32 5d 5d 0a 20 20 20 20 20 20 7d 0a 20 20  $r2]].      }.  
15e0: 20 20 20 20 69 66 20 7b 24 6f 6b 7d 20 7b 0a 20      if {$ok} {. 
15f0: 20 20 20 20 20 20 20 73 65 74 20 6f 6e 65 20 31         set one 1
1600: 0a 20 20 20 20 20 20 20 20 66 6f 72 65 61 63 68  .        foreach
1610: 20 69 64 78 20 24 6f 6d 69 74 6c 69 73 74 20 7b   idx $omitlist {
1620: 73 65 74 20 72 32 20 5b 6c 72 65 70 6c 61 63 65  set r2 [lreplace
1630: 20 24 72 32 20 24 69 64 78 20 24 69 64 78 5d 7d   $r2 $idx $idx]}
1640: 0a 20 20 20 20 20 20 20 20 6c 61 70 70 65 6e 64  .        lappend
1650: 20 72 72 65 74 20 5b 63 6f 6e 63 61 74 20 24 72   rret [concat $r
1660: 31 20 24 72 32 5d 0a 20 20 20 20 20 20 7d 0a 20  1 $r2].      }. 
1670: 20 20 20 7d 0a 0a 20 20 20 20 69 66 20 7b 24 69     }..    if {$i
1680: 73 6c 65 66 74 20 26 26 20 24 6f 6e 65 3d 3d 30  sleft && $one==0
1690: 7d 20 7b 0a 20 20 20 20 20 20 6c 61 70 70 65 6e  } {.      lappen
16a0: 64 20 72 72 65 74 20 5b 63 6f 6e 63 61 74 20 24  d rret [concat $
16b0: 72 31 20 24 6e 75 6c 6c 72 6f 77 6c 69 73 74 5d  r1 $nullrowlist]
16c0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 0a 20 20  .    }.  }.  .  
16d0: 6c 69 73 74 20 24 63 72 65 74 20 24 72 72 65 74  list $cret $rret
16e0: 0a 7d 0a 0a 70 72 6f 63 20 74 65 5f 74 62 6c 6a  .}..proc te_tblj
16f0: 6f 69 6e 20 7b 64 62 20 74 31 20 74 32 20 61 72  oin {db t1 t2 ar
1700: 67 73 7d 20 7b 0a 20 20 74 65 5f 6a 6f 69 6e 20  gs} {.  te_join 
1710: 5b 74 65 5f 72 65 61 64 5f 74 62 6c 20 24 64 62  [te_read_tbl $db
1720: 20 24 74 31 5d 20 5b 74 65 5f 72 65 61 64 5f 74   $t1] [te_read_t
1730: 62 6c 20 24 64 62 20 24 74 32 5d 20 7b 2a 7d 24  bl $db $t2] {*}$
1740: 61 72 67 73 0a 7d 0a 0a 70 72 6f 63 20 74 65 5f  args.}..proc te_
1750: 61 70 70 6c 79 5f 61 66 66 69 6e 69 74 79 20 7b  apply_affinity {
1760: 61 66 66 69 6e 69 74 79 20 74 79 70 65 76 61 72  affinity typevar
1770: 20 76 61 6c 76 61 72 7d 20 7b 0a 20 20 75 70 76   valvar} {.  upv
1780: 61 72 20 24 74 79 70 65 76 61 72 20 74 79 70 65  ar $typevar type
1790: 0a 20 20 75 70 76 61 72 20 24 76 61 6c 76 61 72  .  upvar $valvar
17a0: 20 76 61 6c 0a 0a 20 20 73 77 69 74 63 68 20 2d   val..  switch -
17b0: 2d 20 24 61 66 66 69 6e 69 74 79 20 7b 0a 20 20  - $affinity {.  
17c0: 20 20 69 6e 74 65 67 65 72 20 7b 0a 20 20 20 20    integer {.    
17d0: 20 20 69 66 20 7b 5b 73 74 72 69 6e 67 20 69 73    if {[string is
17e0: 20 64 6f 75 62 6c 65 20 24 76 61 6c 5d 7d 20 7b   double $val]} {
17f0: 20 73 65 74 20 74 79 70 65 20 52 45 41 4c 20 7d   set type REAL }
1800: 0a 20 20 20 20 20 20 69 66 20 7b 5b 73 74 72 69  .      if {[stri
1810: 6e 67 20 69 73 20 77 69 64 65 69 6e 74 65 67 65  ng is wideintege
1820: 72 20 24 76 61 6c 5d 7d 20 7b 20 73 65 74 20 74  r $val]} { set t
1830: 79 70 65 20 49 4e 54 45 47 45 52 20 7d 0a 20 20  ype INTEGER }.  
1840: 20 20 20 20 69 66 20 7b 24 74 79 70 65 20 3d 3d      if {$type ==
1850: 20 22 52 45 41 4c 22 20 26 26 20 69 6e 74 28 24   "REAL" && int($
1860: 76 61 6c 29 3d 3d 24 76 61 6c 7d 20 7b 20 0a 20  val)==$val} { . 
1870: 20 20 20 20 20 20 20 73 65 74 20 74 79 70 65 20         set type 
1880: 49 4e 54 45 47 45 52 20 0a 20 20 20 20 20 20 20  INTEGER .       
1890: 20 73 65 74 20 76 61 6c 20 5b 65 78 70 72 20 7b   set val [expr {
18a0: 69 6e 74 28 24 76 61 6c 29 7d 5d 0a 20 20 20 20  int($val)}].    
18b0: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 74 65    }.    }.    te
18c0: 78 74 20 7b 0a 20 20 20 20 20 20 73 65 74 20 74  xt {.      set t
18d0: 79 70 65 20 54 45 58 54 0a 20 20 20 20 7d 0a 20  ype TEXT.    }. 
18e0: 20 20 20 6e 6f 6e 65 20 7b 20 7d 0a 0a 20 20 20     none { }..   
18f0: 20 64 65 66 61 75 6c 74 20 7b 20 65 72 72 6f 72   default { error
1900: 20 22 69 6e 76 61 6c 69 64 20 61 66 66 69 6e 69   "invalid affini
1910: 74 79 3a 20 24 61 66 66 69 6e 69 74 79 22 20 7d  ty: $affinity" }
1920: 0a 20 20 7d 0a 7d 0a 0a 23 2d 2d 2d 2d 2d 2d 2d  .  }.}..#-------
1930: 2d 2d 2d 0a 23 20 74 65 5f 65 71 75 61 6c 73 20  ---.# te_equals 
1940: 3f 53 57 49 54 43 48 45 53 3f 20 63 31 20 63 32  ?SWITCHES? c1 c2
1950: 20 63 6f 6c 73 31 20 72 6f 77 31 20 63 6f 6c 73   cols1 row1 cols
1960: 32 20 72 6f 77 32 0a 23 0a 70 72 6f 63 20 74 65  2 row2.#.proc te
1970: 5f 65 71 75 61 6c 73 20 7b 61 72 67 73 7d 20 7b  _equals {args} {
1980: 0a 0a 20 20 69 66 20 7b 5b 6c 6c 65 6e 67 74 68  ..  if {[llength
1990: 20 24 61 72 67 73 5d 3c 36 7d 20 7b 65 72 72 6f   $args]<6} {erro
19a0: 72 20 22 69 6e 76 61 6c 69 64 20 61 72 67 75 6d  r "invalid argum
19b0: 65 6e 74 73 20 74 6f 20 74 65 5f 65 71 75 61 6c  ents to te_equal
19c0: 73 22 7d 0a 20 20 66 6f 72 65 61 63 68 20 7b 63  s"}.  foreach {c
19d0: 31 20 63 32 20 63 6f 6c 73 31 20 72 6f 77 31 20  1 c2 cols1 row1 
19e0: 63 6f 6c 73 32 20 72 6f 77 32 7d 20 5b 6c 72 61  cols2 row2} [lra
19f0: 6e 67 65 20 24 61 72 67 73 20 65 6e 64 2d 35 20  nge $args end-5 
1a00: 65 6e 64 5d 20 62 72 65 61 6b 0a 0a 20 20 73 65  end] break..  se
1a10: 74 20 6e 6f 63 61 73 65 20 30 0a 20 20 73 65 74  t nocase 0.  set
1a20: 20 61 66 66 69 6e 69 74 79 20 6e 6f 6e 65 0a 0a   affinity none..
1a30: 20 20 66 6f 72 20 7b 73 65 74 20 69 20 30 7d 20    for {set i 0} 
1a40: 7b 24 69 20 3c 20 28 5b 6c 6c 65 6e 67 74 68 20  {$i < ([llength 
1a50: 24 61 72 67 73 5d 2d 36 29 7d 20 7b 69 6e 63 72  $args]-6)} {incr
1a60: 20 69 7d 20 7b 0a 20 20 20 20 73 65 74 20 61 20   i} {.    set a 
1a70: 5b 6c 69 6e 64 65 78 20 24 61 72 67 73 20 24 69  [lindex $args $i
1a80: 5d 0a 20 20 20 20 73 77 69 74 63 68 20 2d 2d 20  ].    switch -- 
1a90: 24 61 20 7b 0a 20 20 20 20 20 20 2d 6e 6f 63 61  $a {.      -noca
1aa0: 73 65 20 7b 0a 20 20 20 20 20 20 20 20 73 65 74  se {.        set
1ab0: 20 6e 6f 63 61 73 65 20 31 0a 20 20 20 20 20 20   nocase 1.      
1ac0: 7d 0a 20 20 20 20 20 20 2d 61 66 66 69 6e 69 74  }.      -affinit
1ad0: 79 20 7b 0a 20 20 20 20 20 20 20 20 73 65 74 20  y {.        set 
1ae0: 61 66 66 69 6e 69 74 79 20 5b 73 74 72 69 6e 67  affinity [string
1af0: 20 74 6f 6c 6f 77 65 72 20 5b 6c 69 6e 64 65 78   tolower [lindex
1b00: 20 24 61 72 67 73 20 5b 69 6e 63 72 20 69 5d 5d   $args [incr i]]
1b10: 5d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ].      }.      
1b20: 64 65 66 61 75 6c 74 20 7b 0a 20 20 20 20 20 20  default {.      
1b30: 20 20 65 72 72 6f 72 20 22 69 6e 76 61 6c 69 64    error "invalid
1b40: 20 61 72 67 75 6d 65 6e 74 73 20 74 6f 20 74 65   arguments to te
1b50: 5f 65 71 75 61 6c 73 22 0a 20 20 20 20 20 20 7d  _equals".      }
1b60: 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 73 65  .    }.  }..  se
1b70: 74 20 69 64 78 32 20 5b 69 66 20 7b 5b 73 74 72  t idx2 [if {[str
1b80: 69 6e 67 20 69 73 20 69 6e 74 65 67 65 72 20 24  ing is integer $
1b90: 63 32 5d 7d 20 7b 20 73 65 74 20 63 32 20 7d 20  c2]} { set c2 } 
1ba0: 65 6c 73 65 20 7b 20 6c 73 65 61 72 63 68 20 24  else { lsearch $
1bb0: 63 6f 6c 73 32 20 24 63 32 20 7d 5d 0a 20 20 73  cols2 $c2 }].  s
1bc0: 65 74 20 69 64 78 31 20 5b 69 66 20 7b 5b 73 74  et idx1 [if {[st
1bd0: 72 69 6e 67 20 69 73 20 69 6e 74 65 67 65 72 20  ring is integer 
1be0: 24 63 31 5d 7d 20 7b 20 73 65 74 20 63 31 20 7d  $c1]} { set c1 }
1bf0: 20 65 6c 73 65 20 7b 20 6c 73 65 61 72 63 68 20   else { lsearch 
1c00: 24 63 6f 6c 73 31 20 24 63 31 20 7d 5d 0a 0a 20  $cols1 $c1 }].. 
1c10: 20 73 65 74 20 74 31 20 5b 6c 69 6e 64 65 78 20   set t1 [lindex 
1c20: 24 72 6f 77 31 20 24 69 64 78 31 20 30 5d 0a 20  $row1 $idx1 0]. 
1c30: 20 73 65 74 20 74 32 20 5b 6c 69 6e 64 65 78 20   set t2 [lindex 
1c40: 24 72 6f 77 32 20 24 69 64 78 32 20 30 5d 0a 20  $row2 $idx2 0]. 
1c50: 20 73 65 74 20 76 31 20 5b 6c 69 6e 64 65 78 20   set v1 [lindex 
1c60: 24 72 6f 77 31 20 24 69 64 78 31 20 31 5d 0a 20  $row1 $idx1 1]. 
1c70: 20 73 65 74 20 76 32 20 5b 6c 69 6e 64 65 78 20   set v2 [lindex 
1c80: 24 72 6f 77 32 20 24 69 64 78 32 20 31 5d 0a 0a  $row2 $idx2 1]..
1c90: 20 20 74 65 5f 61 70 70 6c 79 5f 61 66 66 69 6e    te_apply_affin
1ca0: 69 74 79 20 24 61 66 66 69 6e 69 74 79 20 74 31  ity $affinity t1
1cb0: 20 76 31 0a 20 20 74 65 5f 61 70 70 6c 79 5f 61   v1.  te_apply_a
1cc0: 66 66 69 6e 69 74 79 20 24 61 66 66 69 6e 69 74  ffinity $affinit
1cd0: 79 20 74 32 20 76 32 0a 0a 20 20 69 66 20 7b 24  y t2 v2..  if {$
1ce0: 74 31 20 3d 3d 20 22 4e 55 4c 4c 22 20 7c 7c 20  t1 == "NULL" || 
1cf0: 24 74 32 20 3d 3d 20 22 4e 55 4c 4c 22 7d 20 7b  $t2 == "NULL"} {
1d00: 20 72 65 74 75 72 6e 20 30 20 7d 0a 20 20 69 66   return 0 }.  if
1d10: 20 7b 24 6e 6f 63 61 73 65 20 26 26 20 24 74 31   {$nocase && $t1
1d20: 20 3d 3d 20 22 54 45 58 54 22 7d 20 7b 20 73 65   == "TEXT"} { se
1d30: 74 20 76 31 20 5b 73 74 72 69 6e 67 20 74 6f 6c  t v1 [string tol
1d40: 6f 77 65 72 20 24 76 31 5d 20 7d 0a 20 20 69 66  ower $v1] }.  if
1d50: 20 7b 24 6e 6f 63 61 73 65 20 26 26 20 24 74 32   {$nocase && $t2
1d60: 20 3d 3d 20 22 54 45 58 54 22 7d 20 7b 20 73 65   == "TEXT"} { se
1d70: 74 20 76 32 20 5b 73 74 72 69 6e 67 20 74 6f 6c  t v2 [string tol
1d80: 6f 77 65 72 20 24 76 32 5d 20 7d 0a 0a 0a 20 20  ower $v2] }...  
1d90: 73 65 74 20 72 65 73 20 5b 65 78 70 72 20 7b 24  set res [expr {$
1da0: 74 31 20 3d 3d 20 24 74 32 20 26 26 20 5b 73 74  t1 == $t2 && [st
1db0: 72 69 6e 67 20 65 71 75 61 6c 20 24 76 31 20 24  ring equal $v1 $
1dc0: 76 32 5d 7d 5d 0a 20 20 72 65 74 75 72 6e 20 24  v2]}].  return $
1dd0: 72 65 73 0a 7d 0a 0a 70 72 6f 63 20 74 65 5f 66  res.}..proc te_f
1de0: 61 6c 73 65 20 7b 61 72 67 73 7d 20 7b 20 72 65  alse {args} { re
1df0: 74 75 72 6e 20 30 20 7d 0a 70 72 6f 63 20 74 65  turn 0 }.proc te
1e00: 5f 74 72 75 65 20 20 7b 61 72 67 73 7d 20 7b 20  _true  {args} { 
1e10: 72 65 74 75 72 6e 20 31 20 7d 0a 0a 70 72 6f 63  return 1 }..proc
1e20: 20 74 65 5f 61 6e 64 20 7b 61 72 67 73 7d 20 7b   te_and {args} {
1e30: 0a 20 20 66 6f 72 65 61 63 68 20 61 20 5b 6c 72  .  foreach a [lr
1e40: 61 6e 67 65 20 24 61 72 67 73 20 30 20 65 6e 64  ange $args 0 end
1e50: 2d 34 5d 20 7b 0a 20 20 20 20 73 65 74 20 72 65  -4] {.    set re
1e60: 73 20 5b 65 76 61 6c 20 24 61 20 5b 6c 72 61 6e  s [eval $a [lran
1e70: 67 65 20 24 61 72 67 73 20 65 6e 64 2d 33 20 65  ge $args end-3 e
1e80: 6e 64 5d 5d 0a 20 20 20 20 69 66 20 7b 24 72 65  nd]].    if {$re
1e90: 73 20 3d 3d 20 30 7d 20 7b 72 65 74 75 72 6e 20  s == 0} {return 
1ea0: 30 7d 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  0}.  }.  return 
1eb0: 31 0a 7d 0a 0a 0a 70 72 6f 63 20 74 65 5f 64 61  1.}...proc te_da
1ec0: 74 61 73 65 74 5f 65 71 20 7b 74 65 73 74 6e 61  taset_eq {testna
1ed0: 6d 65 20 67 6f 74 20 65 78 70 65 63 74 65 64 7d  me got expected}
1ee0: 20 7b 0a 20 20 75 70 6c 65 76 65 6c 20 23 30 20   {.  uplevel #0 
1ef0: 5b 6c 69 73 74 20 64 6f 5f 74 65 73 74 20 24 74  [list do_test $t
1f00: 65 73 74 6e 61 6d 65 20 5b 6c 69 73 74 20 73 65  estname [list se
1f10: 74 20 7b 7d 20 24 67 6f 74 5d 20 24 65 78 70 65  t {} $got] $expe
1f20: 63 74 65 64 5d 0a 7d 0a 70 72 6f 63 20 74 65 5f  cted].}.proc te_
1f30: 64 61 74 61 73 65 74 5f 65 71 5f 75 6e 6f 72 64  dataset_eq_unord
1f40: 65 72 65 64 20 7b 74 65 73 74 6e 61 6d 65 20 67  ered {testname g
1f50: 6f 74 20 65 78 70 65 63 74 65 64 7d 20 7b 0a 20  ot expected} {. 
1f60: 20 6c 73 65 74 20 67 6f 74 20 20 20 20 20 20 31   lset got      1
1f70: 20 5b 6c 73 6f 72 74 20 5b 6c 69 6e 64 65 78 20   [lsort [lindex 
1f80: 24 67 6f 74 20 31 5d 5d 0a 20 20 6c 73 65 74 20  $got 1]].  lset 
1f90: 65 78 70 65 63 74 65 64 20 31 20 5b 6c 73 6f 72  expected 1 [lsor
1fa0: 74 20 5b 6c 69 6e 64 65 78 20 24 65 78 70 65 63  t [lindex $expec
1fb0: 74 65 64 20 31 5d 5d 0a 20 20 74 65 5f 64 61 74  ted 1]].  te_dat
1fc0: 61 73 65 74 5f 65 71 20 24 74 65 73 74 6e 61 6d  aset_eq $testnam
1fd0: 65 20 24 67 6f 74 20 24 65 78 70 65 63 74 65 64  e $got $expected
1fe0: 0a 7d 0a 0a 70 72 6f 63 20 74 65 5f 64 61 74 61  .}..proc te_data
1ff0: 73 65 74 5f 6e 65 20 7b 74 65 73 74 6e 61 6d 65  set_ne {testname
2000: 20 67 6f 74 20 75 6e 65 78 70 65 63 74 65 64 7d   got unexpected}
2010: 20 7b 0a 20 20 75 70 6c 65 76 65 6c 20 23 30 20   {.  uplevel #0 
2020: 5b 6c 69 73 74 20 64 6f 5f 74 65 73 74 20 24 74  [list do_test $t
2030: 65 73 74 6e 61 6d 65 20 5b 6c 69 73 74 20 73 74  estname [list st
2040: 72 69 6e 67 20 65 71 75 61 6c 20 24 67 6f 74 20  ring equal $got 
2050: 24 75 6e 65 78 70 65 63 74 65 64 5d 20 30 5d 0a  $unexpected] 0].
2060: 7d 0a 70 72 6f 63 20 74 65 5f 64 61 74 61 73 65  }.proc te_datase
2070: 74 5f 6e 65 5f 75 6e 6f 72 64 65 72 65 64 20 7b  t_ne_unordered {
2080: 74 65 73 74 6e 61 6d 65 20 67 6f 74 20 75 6e 65  testname got une
2090: 78 70 65 63 74 65 64 7d 20 7b 0a 20 20 6c 73 65  xpected} {.  lse
20a0: 74 20 67 6f 74 20 20 20 20 20 20 31 20 5b 6c 73  t got      1 [ls
20b0: 6f 72 74 20 5b 6c 69 6e 64 65 78 20 24 67 6f 74  ort [lindex $got
20c0: 20 31 5d 5d 0a 20 20 6c 73 65 74 20 75 6e 65 78   1]].  lset unex
20d0: 70 65 63 74 65 64 20 31 20 5b 6c 73 6f 72 74 20  pected 1 [lsort 
20e0: 5b 6c 69 6e 64 65 78 20 24 75 6e 65 78 70 65 63  [lindex $unexpec
20f0: 74 65 64 20 31 5d 5d 0a 20 20 74 65 5f 64 61 74  ted 1]].  te_dat
2100: 61 73 65 74 5f 6e 65 20 24 74 65 73 74 6e 61 6d  aset_ne $testnam
2110: 65 20 24 67 6f 74 20 24 75 6e 65 78 70 65 63 74  e $got $unexpect
2120: 65 64 0a 7d 0a 0a 0a 23 2d 2d 2d 2d 2d 2d 2d 2d  ed.}...#--------
2130: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
2140: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
2150: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
2160: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
2170: 2d 0a 23 0a 70 72 6f 63 20 74 65 73 74 5f 6a 6f  -.#.proc test_jo
2180: 69 6e 20 7b 74 6e 20 73 71 6c 6a 6f 69 6e 20 74  in {tn sqljoin t
2190: 62 6c 6a 6f 69 6e 61 72 67 73 7d 20 7b 0a 20 20  bljoinargs} {.  
21a0: 73 65 74 20 73 71 6c 20 5b 74 65 5f 72 65 61 64  set sql [te_read
21b0: 5f 73 71 6c 20 64 62 20 22 53 45 4c 45 43 54 20  _sql db "SELECT 
21c0: 2a 20 46 52 4f 4d 20 24 73 71 6c 6a 6f 69 6e 22  * FROM $sqljoin"
21d0: 5d 0a 20 20 73 65 74 20 74 65 20 20 5b 74 65 5f  ].  set te  [te_
21e0: 74 62 6c 6a 6f 69 6e 20 64 62 20 7b 2a 7d 24 74  tbljoin db {*}$t
21f0: 62 6c 6a 6f 69 6e 61 72 67 73 5d 0a 20 20 74 65  bljoinargs].  te
2200: 5f 64 61 74 61 73 65 74 5f 65 71 5f 75 6e 6f 72  _dataset_eq_unor
2210: 64 65 72 65 64 20 24 74 6e 20 24 73 71 6c 20 24  dered $tn $sql $
2220: 74 65 0a 7d 0a 0a 64 72 6f 70 5f 61 6c 6c 5f 74  te.}..drop_all_t
2230: 61 62 6c 65 73 0a 64 6f 5f 65 78 65 63 73 71 6c  ables.do_execsql
2240: 5f 74 65 73 74 20 65 5f 73 65 6c 65 63 74 2d 32  _test e_select-2
2250: 2e 30 20 7b 0a 20 20 43 52 45 41 54 45 20 54 41  .0 {.  CREATE TA
2260: 42 4c 45 20 74 31 28 61 2c 20 62 29 3b 0a 20 20  BLE t1(a, b);.  
2270: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 28  CREATE TABLE t2(
2280: 61 2c 20 62 29 3b 0a 20 20 43 52 45 41 54 45 20  a, b);.  CREATE 
2290: 54 41 42 4c 45 20 74 33 28 62 20 43 4f 4c 4c 41  TABLE t3(b COLLA
22a0: 54 45 20 6e 6f 63 61 73 65 29 3b 0a 0a 20 20 49  TE nocase);..  I
22b0: 4e 53 45 52 54 20 49 4e 54 4f 20 74 31 20 56 41  NSERT INTO t1 VA
22c0: 4c 55 45 53 28 32 2c 20 27 42 27 29 3b 0a 20 20  LUES(2, 'B');.  
22d0: 49 4e 53 45 52 54 20 49 4e 54 4f 20 74 31 20 56  INSERT INTO t1 V
22e0: 41 4c 55 45 53 28 31 2c 20 27 41 27 29 3b 0a 20  ALUES(1, 'A');. 
22f0: 20 49 4e 53 45 52 54 20 49 4e 54 4f 20 74 31 20   INSERT INTO t1 
2300: 56 41 4c 55 45 53 28 34 2c 20 27 44 27 29 3b 0a  VALUES(4, 'D');.
2310: 20 20 49 4e 53 45 52 54 20 49 4e 54 4f 20 74 31    INSERT INTO t1
2320: 20 56 41 4c 55 45 53 28 4e 55 4c 4c 2c 20 4e 55   VALUES(NULL, NU
2330: 4c 4c 29 3b 0a 20 20 49 4e 53 45 52 54 20 49 4e  LL);.  INSERT IN
2340: 54 4f 20 74 31 20 56 41 4c 55 45 53 28 33 2c 20  TO t1 VALUES(3, 
2350: 4e 55 4c 4c 29 3b 0a 0a 20 20 49 4e 53 45 52 54  NULL);..  INSERT
2360: 20 49 4e 54 4f 20 74 32 20 56 41 4c 55 45 53 28   INTO t2 VALUES(
2370: 31 2c 20 27 41 27 29 3b 0a 20 20 49 4e 53 45 52  1, 'A');.  INSER
2380: 54 20 49 4e 54 4f 20 74 32 20 56 41 4c 55 45 53  T INTO t2 VALUES
2390: 28 32 2c 20 4e 55 4c 4c 29 3b 0a 20 20 49 4e 53  (2, NULL);.  INS
23a0: 45 52 54 20 49 4e 54 4f 20 74 32 20 56 41 4c 55  ERT INTO t2 VALU
23b0: 45 53 28 35 2c 20 27 45 27 29 3b 0a 20 20 49 4e  ES(5, 'E');.  IN
23c0: 53 45 52 54 20 49 4e 54 4f 20 74 32 20 56 41 4c  SERT INTO t2 VAL
23d0: 55 45 53 28 4e 55 4c 4c 2c 20 4e 55 4c 4c 29 3b  UES(NULL, NULL);
23e0: 0a 20 20 49 4e 53 45 52 54 20 49 4e 54 4f 20 74  .  INSERT INTO t
23f0: 32 20 56 41 4c 55 45 53 28 33 2c 20 27 43 27 29  2 VALUES(3, 'C')
2400: 3b 0a 0a 20 20 49 4e 53 45 52 54 20 49 4e 54 4f  ;..  INSERT INTO
2410: 20 74 33 20 56 41 4c 55 45 53 28 27 61 27 29 3b   t3 VALUES('a');
2420: 0a 20 20 49 4e 53 45 52 54 20 49 4e 54 4f 20 74  .  INSERT INTO t
2430: 33 20 56 41 4c 55 45 53 28 27 63 27 29 3b 0a 20  3 VALUES('c');. 
2440: 20 49 4e 53 45 52 54 20 49 4e 54 4f 20 74 33 20   INSERT INTO t3 
2450: 56 41 4c 55 45 53 28 27 62 27 29 3b 0a 7d 20 7b  VALUES('b');.} {
2460: 7d 0a 0a 66 6f 72 65 61 63 68 20 7b 74 6e 20 69  }..foreach {tn i
2470: 6e 64 65 78 65 73 7d 20 7b 0a 20 20 65 5f 73 65  ndexes} {.  e_se
2480: 6c 65 63 74 2d 32 2e 31 2e 31 20 7b 20 7d 0a 20  lect-2.1.1 { }. 
2490: 20 65 5f 73 65 6c 65 63 74 2d 32 2e 31 2e 32 20   e_select-2.1.2 
24a0: 7b 20 43 52 45 41 54 45 20 49 4e 44 45 58 20 69  { CREATE INDEX i
24b0: 31 20 4f 4e 20 74 31 28 61 29 20 7d 0a 20 20 65  1 ON t1(a) }.  e
24c0: 5f 73 65 6c 65 63 74 2d 32 2e 31 2e 33 20 7b 20  _select-2.1.3 { 
24d0: 43 52 45 41 54 45 20 49 4e 44 45 58 20 69 31 20  CREATE INDEX i1 
24e0: 4f 4e 20 74 32 28 61 29 20 7d 0a 20 20 65 5f 73  ON t2(a) }.  e_s
24f0: 65 6c 65 63 74 2d 32 2e 31 2e 34 20 7b 20 43 52  elect-2.1.4 { CR
2500: 45 41 54 45 20 49 4e 44 45 58 20 69 31 20 4f 4e  EATE INDEX i1 ON
2510: 20 74 33 28 62 29 20 7d 0a 7d 20 7b 0a 0a 20 20   t3(b) }.} {..  
2520: 63 61 74 63 68 73 71 6c 20 7b 20 44 52 4f 50 20  catchsql { DROP 
2530: 49 4e 44 45 58 20 69 31 20 7d 0a 20 20 63 61 74  INDEX i1 }.  cat
2540: 63 68 73 71 6c 20 7b 20 44 52 4f 50 20 49 4e 44  chsql { DROP IND
2550: 45 58 20 69 32 20 7d 0a 20 20 63 61 74 63 68 73  EX i2 }.  catchs
2560: 71 6c 20 7b 20 44 52 4f 50 20 49 4e 44 45 58 20  ql { DROP INDEX 
2570: 69 33 20 7d 0a 20 20 65 78 65 63 73 71 6c 20 24  i3 }.  execsql $
2580: 69 6e 64 65 78 65 73 0a 0a 20 20 23 20 45 56 49  indexes..  # EVI
2590: 44 45 4e 43 45 2d 4f 46 3a 20 52 2d 34 39 38 37  DENCE-OF: R-4987
25a0: 32 2d 30 33 31 39 32 20 49 66 20 74 68 65 20 6a  2-03192 If the j
25b0: 6f 69 6e 2d 6f 70 65 72 61 74 6f 72 20 69 73 20  oin-operator is 
25c0: 22 43 52 4f 53 53 20 4a 4f 49 4e 22 2c 0a 20 20  "CROSS JOIN",.  
25d0: 23 20 22 49 4e 4e 45 52 20 4a 4f 49 4e 22 2c 20  # "INNER JOIN", 
25e0: 22 4a 4f 49 4e 22 20 6f 72 20 61 20 63 6f 6d 6d  "JOIN" or a comm
25f0: 61 20 28 22 2c 22 29 20 61 6e 64 20 74 68 65 72  a (",") and ther
2600: 65 20 69 73 20 6e 6f 20 4f 4e 20 6f 72 20 55 53  e is no ON or US
2610: 49 4e 47 0a 20 20 23 20 63 6c 61 75 73 65 2c 20  ING.  # clause, 
2620: 74 68 65 6e 20 74 68 65 20 72 65 73 75 6c 74 20  then the result 
2630: 6f 66 20 74 68 65 20 6a 6f 69 6e 20 69 73 20 73  of the join is s
2640: 69 6d 70 6c 79 20 74 68 65 20 63 61 72 74 65 73  imply the cartes
2650: 69 61 6e 20 70 72 6f 64 75 63 74 20 6f 66 0a 20  ian product of. 
2660: 20 23 20 74 68 65 20 6c 65 66 74 20 61 6e 64 20   # the left and 
2670: 72 69 67 68 74 2d 68 61 6e 64 20 64 61 74 61 73  right-hand datas
2680: 65 74 73 2e 0a 20 20 23 0a 20 20 23 20 45 56 49  ets..  #.  # EVI
2690: 44 45 4e 43 45 2d 4f 46 3a 20 52 2d 34 36 32 35  DENCE-OF: R-4625
26a0: 36 2d 35 37 32 34 33 20 54 68 65 72 65 20 69 73  6-57243 There is
26b0: 20 6e 6f 20 64 69 66 66 65 72 65 6e 63 65 20 62   no difference b
26c0: 65 74 77 65 65 6e 20 74 68 65 20 22 49 4e 4e 45  etween the "INNE
26d0: 52 0a 20 20 23 20 4a 4f 49 4e 22 2c 20 22 4a 4f  R.  # JOIN", "JO
26e0: 49 4e 22 20 61 6e 64 20 22 2c 22 20 6a 6f 69 6e  IN" and "," join
26f0: 20 6f 70 65 72 61 74 6f 72 73 2e 0a 20 20 23 0a   operators..  #.
2700: 20 20 23 20 45 56 49 44 45 4e 43 45 2d 4f 46 3a    # EVIDENCE-OF:
2710: 20 52 2d 32 35 30 37 31 2d 32 31 32 30 32 20 54   R-25071-21202 T
2720: 68 65 20 22 43 52 4f 53 53 20 4a 4f 49 4e 22 20  he "CROSS JOIN" 
2730: 6a 6f 69 6e 20 6f 70 65 72 61 74 6f 72 20 70 72  join operator pr
2740: 6f 64 75 63 65 73 20 74 68 65 0a 20 20 23 20 73  oduces the.  # s
2750: 61 6d 65 20 72 65 73 75 6c 74 20 61 73 20 74 68  ame result as th
2760: 65 20 22 49 4e 4e 45 52 20 4a 4f 49 4e 22 2c 20  e "INNER JOIN", 
2770: 22 4a 4f 49 4e 22 20 61 6e 64 20 22 2c 22 20 6f  "JOIN" and "," o
2780: 70 65 72 61 74 6f 72 73 0a 20 20 23 0a 20 20 74  perators.  #.  t
2790: 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e 31  est_join $tn.1.1
27a0: 20 20 22 74 31 2c 20 74 32 22 20 20 20 20 20 20    "t1, t2"      
27b0: 20 20 20 20 20 20 20 20 20 20 7b 74 31 20 74 32            {t1 t2
27c0: 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74  }.  test_join $t
27d0: 6e 2e 31 2e 32 20 20 22 74 31 20 49 4e 4e 45 52  n.1.2  "t1 INNER
27e0: 20 4a 4f 49 4e 20 74 32 22 20 20 20 20 20 20 7b   JOIN t2"      {
27f0: 74 31 20 74 32 7d 0a 20 20 74 65 73 74 5f 6a 6f  t1 t2}.  test_jo
2800: 69 6e 20 24 74 6e 2e 31 2e 33 20 20 22 74 31 20  in $tn.1.3  "t1 
2810: 43 52 4f 53 53 20 4a 4f 49 4e 20 74 32 22 20 20  CROSS JOIN t2"  
2820: 20 20 20 20 7b 74 31 20 74 32 7d 0a 20 20 74 65      {t1 t2}.  te
2830: 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e 34 20  st_join $tn.1.4 
2840: 20 22 74 31 20 4a 4f 49 4e 20 74 32 22 20 20 20   "t1 JOIN t2"   
2850: 20 20 20 20 20 20 20 20 20 7b 74 31 20 74 32 7d           {t1 t2}
2860: 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e  .  test_join $tn
2870: 2e 31 2e 35 20 20 22 74 32 2c 20 74 33 22 20 20  .1.5  "t2, t3"  
2880: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7b 74                {t
2890: 32 20 74 33 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  2 t3}.  test_joi
28a0: 6e 20 24 74 6e 2e 31 2e 36 20 20 22 74 32 20 49  n $tn.1.6  "t2 I
28b0: 4e 4e 45 52 20 4a 4f 49 4e 20 74 33 22 20 20 20  NNER JOIN t3"   
28c0: 20 20 20 7b 74 32 20 74 33 7d 0a 20 20 74 65 73     {t2 t3}.  tes
28d0: 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e 37 20 20  t_join $tn.1.7  
28e0: 22 74 32 20 43 52 4f 53 53 20 4a 4f 49 4e 20 74  "t2 CROSS JOIN t
28f0: 33 22 20 20 20 20 20 20 7b 74 32 20 74 33 7d 0a  3"      {t2 t3}.
2900: 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e    test_join $tn.
2910: 31 2e 38 20 20 22 74 32 20 4a 4f 49 4e 20 74 33  1.8  "t2 JOIN t3
2920: 22 20 20 20 20 20 20 20 20 20 20 20 20 7b 74 32  "            {t2
2930: 20 74 33 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e   t3}.  test_join
2940: 20 24 74 6e 2e 31 2e 39 20 20 22 74 32 2c 20 74   $tn.1.9  "t2, t
2950: 32 20 41 53 20 78 22 20 20 20 20 20 20 20 20 20  2 AS x"         
2960: 20 20 7b 74 32 20 74 32 7d 0a 20 20 74 65 73 74    {t2 t2}.  test
2970: 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e 31 30 20 22  _join $tn.1.10 "
2980: 74 32 20 49 4e 4e 45 52 20 4a 4f 49 4e 20 74 32  t2 INNER JOIN t2
2990: 20 41 53 20 78 22 20 7b 74 32 20 74 32 7d 0a 20   AS x" {t2 t2}. 
29a0: 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31   test_join $tn.1
29b0: 2e 31 31 20 22 74 32 20 43 52 4f 53 53 20 4a 4f  .11 "t2 CROSS JO
29c0: 49 4e 20 74 32 20 41 53 20 78 22 20 7b 74 32 20  IN t2 AS x" {t2 
29d0: 74 32 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20  t2}.  test_join 
29e0: 24 74 6e 2e 31 2e 31 32 20 22 74 32 20 4a 4f 49  $tn.1.12 "t2 JOI
29f0: 4e 20 74 32 20 41 53 20 78 22 20 20 20 20 20 20  N t2 AS x"      
2a00: 20 7b 74 32 20 74 32 7d 0a 0a 20 20 23 20 45 56   {t2 t2}..  # EV
2a10: 49 44 45 4e 43 45 2d 4f 46 3a 20 52 2d 33 38 34  IDENCE-OF: R-384
2a20: 36 35 2d 30 33 36 31 36 20 49 66 20 74 68 65 72  65-03616 If ther
2a30: 65 20 69 73 20 61 6e 20 4f 4e 20 63 6c 61 75 73  e is an ON claus
2a40: 65 20 74 68 65 6e 20 74 68 65 20 4f 4e 0a 20 20  e then the ON.  
2a50: 23 20 65 78 70 72 65 73 73 69 6f 6e 20 69 73 20  # expression is 
2a60: 65 76 61 6c 75 61 74 65 64 20 66 6f 72 20 65 61  evaluated for ea
2a70: 63 68 20 72 6f 77 20 6f 66 20 74 68 65 20 63 61  ch row of the ca
2a80: 72 74 65 73 69 61 6e 20 70 72 6f 64 75 63 74 20  rtesian product 
2a90: 61 73 20 61 0a 20 20 23 20 62 6f 6f 6c 65 61 6e  as a.  # boolean
2aa0: 20 65 78 70 72 65 73 73 69 6f 6e 2e 20 4f 6e 6c   expression. Onl
2ab0: 79 20 72 6f 77 73 20 66 6f 72 20 77 68 69 63 68  y rows for which
2ac0: 20 74 68 65 20 65 78 70 72 65 73 73 69 6f 6e 20   the expression 
2ad0: 65 76 61 6c 75 61 74 65 73 20 74 6f 0a 20 20 23  evaluates to.  #
2ae0: 20 74 72 75 65 20 61 72 65 20 69 6e 63 6c 75 64   true are includ
2af0: 65 64 20 66 72 6f 6d 20 74 68 65 20 64 61 74 61  ed from the data
2b00: 73 65 74 2e 0a 20 20 23 0a 20 20 74 65 73 74 5f  set..  #.  test_
2b10: 6a 6f 69 6e 20 24 74 6e 2e 32 2e 31 20 20 22 74  join $tn.2.1  "t
2b20: 31 2c 20 74 32 20 4f 4e 20 28 74 31 2e 61 3d 74  1, t2 ON (t1.a=t
2b30: 32 2e 61 29 22 20 20 7b 74 31 20 74 32 20 2d 6f  2.a)"  {t1 t2 -o
2b40: 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61  n {te_equals a a
2b50: 7d 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24  }}.  test_join $
2b60: 74 6e 2e 32 2e 32 20 20 22 74 32 2c 20 74 31 20  tn.2.2  "t2, t1 
2b70: 4f 4e 20 28 74 31 2e 61 3d 74 32 2e 61 29 22 20  ON (t1.a=t2.a)" 
2b80: 20 7b 74 32 20 74 31 20 2d 6f 6e 20 7b 74 65 5f   {t2 t1 -on {te_
2b90: 65 71 75 61 6c 73 20 61 20 61 7d 7d 0a 20 20 74  equals a a}}.  t
2ba0: 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32 2e 33  est_join $tn.2.3
2bb0: 20 20 22 74 32 2c 20 74 31 20 4f 4e 20 28 31 29    "t2, t1 ON (1)
2bc0: 22 20 20 20 20 20 20 20 20 20 20 7b 74 32 20 74  "          {t2 t
2bd0: 31 20 2d 6f 6e 20 74 65 5f 74 72 75 65 7d 0a 20  1 -on te_true}. 
2be0: 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32   test_join $tn.2
2bf0: 2e 34 20 20 22 74 32 2c 20 74 31 20 4f 4e 20 28  .4  "t2, t1 ON (
2c00: 4e 55 4c 4c 29 22 20 20 20 20 20 20 20 7b 74 32  NULL)"       {t2
2c10: 20 74 31 20 2d 6f 6e 20 74 65 5f 66 61 6c 73 65   t1 -on te_false
2c20: 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74  }.  test_join $t
2c30: 6e 2e 32 2e 35 20 20 22 74 32 2c 20 74 31 20 4f  n.2.5  "t2, t1 O
2c40: 4e 20 28 31 2e 31 2d 31 2e 31 29 22 20 20 20 20  N (1.1-1.1)"    
2c50: 7b 74 32 20 74 31 20 2d 6f 6e 20 74 65 5f 66 61  {t2 t1 -on te_fa
2c60: 6c 73 65 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e  lse}.  test_join
2c70: 20 24 74 6e 2e 32 2e 36 20 20 22 74 31 2c 20 74   $tn.2.6  "t1, t
2c80: 32 20 4f 4e 20 28 31 2e 31 2d 31 2e 30 29 22 20  2 ON (1.1-1.0)" 
2c90: 20 20 20 7b 74 31 20 74 32 20 2d 6f 6e 20 74 65     {t1 t2 -on te
2ca0: 5f 74 72 75 65 7d 0a 0a 0a 20 20 74 65 73 74 5f  _true}...  test_
2cb0: 6a 6f 69 6e 20 24 74 6e 2e 33 20 22 74 31 20 4c  join $tn.3 "t1 L
2cc0: 45 46 54 20 4a 4f 49 4e 20 74 32 20 4f 4e 20 28  EFT JOIN t2 ON (
2cd0: 74 31 2e 61 3d 74 32 2e 61 29 22 20 7b 74 31 20  t1.a=t2.a)" {t1 
2ce0: 74 32 20 2d 6c 65 66 74 20 2d 6f 6e 20 7b 74 65  t2 -left -on {te
2cf0: 5f 65 71 75 61 6c 73 20 61 20 61 7d 7d 0a 20 20  _equals a a}}.  
2d00: 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 34 20  test_join $tn.4 
2d10: 22 74 31 20 4c 45 46 54 20 4a 4f 49 4e 20 74 32  "t1 LEFT JOIN t2
2d20: 20 55 53 49 4e 47 20 28 61 29 22 20 7b 0a 20 20   USING (a)" {.  
2d30: 20 20 74 31 20 74 32 20 2d 6c 65 66 74 20 2d 75    t1 t2 -left -u
2d40: 73 69 6e 67 20 61 20 2d 6f 6e 20 7b 74 65 5f 65  sing a -on {te_e
2d50: 71 75 61 6c 73 20 61 20 61 7d 0a 20 20 7d 0a 20  quals a a}.  }. 
2d60: 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 35   test_join $tn.5
2d70: 20 22 74 31 20 43 52 4f 53 53 20 4a 4f 49 4e 20   "t1 CROSS JOIN 
2d80: 74 32 20 55 53 49 4e 47 28 62 2c 20 61 29 22 20  t2 USING(b, a)" 
2d90: 7b 0a 20 20 20 20 74 31 20 74 32 20 2d 75 73 69  {.    t1 t2 -usi
2da0: 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65  ng {a b} -on {te
2db0: 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73 20  _and {te_equals 
2dc0: 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20  a a} {te_equals 
2dd0: 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74  b b}}.  }.  test
2de0: 5f 6a 6f 69 6e 20 24 74 6e 2e 36 20 22 74 31 20  _join $tn.6 "t1 
2df0: 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20 74 32 22  NATURAL JOIN t2"
2e00: 20 7b 0a 20 20 20 20 74 31 20 74 32 20 2d 75 73   {.    t1 t2 -us
2e10: 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74  ing {a b} -on {t
2e20: 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73  e_and {te_equals
2e30: 20 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73   a a} {te_equals
2e40: 20 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65 73   b b}}.  }.  tes
2e50: 74 5f 6a 6f 69 6e 20 24 74 6e 2e 37 20 22 74 31  t_join $tn.7 "t1
2e60: 20 4e 41 54 55 52 41 4c 20 49 4e 4e 45 52 20 4a   NATURAL INNER J
2e70: 4f 49 4e 20 74 32 22 20 7b 0a 20 20 20 20 74 31  OIN t2" {.    t1
2e80: 20 74 32 20 2d 75 73 69 6e 67 20 7b 61 20 62 7d   t2 -using {a b}
2e90: 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64 20 7b 74 65   -on {te_and {te
2ea0: 5f 65 71 75 61 6c 73 20 61 20 61 7d 20 7b 74 65  _equals a a} {te
2eb0: 5f 65 71 75 61 6c 73 20 62 20 62 7d 7d 0a 20 20  _equals b b}}.  
2ec0: 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74  }.  test_join $t
2ed0: 6e 2e 38 20 22 74 31 20 4e 41 54 55 52 41 4c 20  n.8 "t1 NATURAL 
2ee0: 43 52 4f 53 53 20 4a 4f 49 4e 20 74 32 22 20 7b  CROSS JOIN t2" {
2ef0: 0a 20 20 20 20 74 31 20 74 32 20 2d 75 73 69 6e  .    t1 t2 -usin
2f00: 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f  g {a b} -on {te_
2f10: 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73 20 61  and {te_equals a
2f20: 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20 62   a} {te_equals b
2f30: 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f   b}}.  }.  test_
2f40: 6a 6f 69 6e 20 24 74 6e 2e 39 20 22 74 31 20 4e  join $tn.9 "t1 N
2f50: 41 54 55 52 41 4c 20 49 4e 4e 45 52 20 4a 4f 49  ATURAL INNER JOI
2f60: 4e 20 74 32 22 20 7b 0a 20 20 20 20 74 31 20 74  N t2" {.    t1 t
2f70: 32 20 2d 75 73 69 6e 67 20 7b 61 20 62 7d 20 2d  2 -using {a b} -
2f80: 6f 6e 20 7b 74 65 5f 61 6e 64 20 7b 74 65 5f 65  on {te_and {te_e
2f90: 71 75 61 6c 73 20 61 20 61 7d 20 7b 74 65 5f 65  quals a a} {te_e
2fa0: 71 75 61 6c 73 20 62 20 62 7d 7d 0a 20 20 7d 0a  quals b b}}.  }.
2fb0: 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e    test_join $tn.
2fc0: 31 30 20 22 74 31 20 4e 41 54 55 52 41 4c 20 4c  10 "t1 NATURAL L
2fd0: 45 46 54 20 4a 4f 49 4e 20 74 32 22 20 7b 0a 20  EFT JOIN t2" {. 
2fe0: 20 20 20 74 31 20 74 32 20 2d 6c 65 66 74 20 2d     t1 t2 -left -
2ff0: 75 73 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20  using {a b} -on 
3000: 7b 74 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61  {te_and {te_equa
3010: 6c 73 20 61 20 61 7d 20 7b 74 65 5f 65 71 75 61  ls a a} {te_equa
3020: 6c 73 20 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74  ls b b}}.  }.  t
3030: 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 31 20  est_join $tn.11 
3040: 22 74 31 20 4e 41 54 55 52 41 4c 20 4c 45 46 54  "t1 NATURAL LEFT
3050: 20 4f 55 54 45 52 20 4a 4f 49 4e 20 74 32 22 20   OUTER JOIN t2" 
3060: 7b 0a 20 20 20 20 74 31 20 74 32 20 2d 6c 65 66  {.    t1 t2 -lef
3070: 74 20 2d 75 73 69 6e 67 20 7b 61 20 62 7d 20 2d  t -using {a b} -
3080: 6f 6e 20 7b 74 65 5f 61 6e 64 20 7b 74 65 5f 65  on {te_and {te_e
3090: 71 75 61 6c 73 20 61 20 61 7d 20 7b 74 65 5f 65  quals a a} {te_e
30a0: 71 75 61 6c 73 20 62 20 62 7d 7d 0a 20 20 7d 0a  quals b b}}.  }.
30b0: 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e    test_join $tn.
30c0: 31 32 20 22 74 32 20 4e 41 54 55 52 41 4c 20 4a  12 "t2 NATURAL J
30d0: 4f 49 4e 20 74 31 22 20 7b 0a 20 20 20 20 74 32  OIN t1" {.    t2
30e0: 20 74 31 20 2d 75 73 69 6e 67 20 7b 61 20 62 7d   t1 -using {a b}
30f0: 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64 20 7b 74 65   -on {te_and {te
3100: 5f 65 71 75 61 6c 73 20 61 20 61 7d 20 7b 74 65  _equals a a} {te
3110: 5f 65 71 75 61 6c 73 20 62 20 62 7d 7d 0a 20 20  _equals b b}}.  
3120: 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74  }.  test_join $t
3130: 6e 2e 31 33 20 22 74 32 20 4e 41 54 55 52 41 4c  n.13 "t2 NATURAL
3140: 20 49 4e 4e 45 52 20 4a 4f 49 4e 20 74 31 22 20   INNER JOIN t1" 
3150: 7b 0a 20 20 20 20 74 32 20 74 31 20 2d 75 73 69  {.    t2 t1 -usi
3160: 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65  ng {a b} -on {te
3170: 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73 20  _and {te_equals 
3180: 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20  a a} {te_equals 
3190: 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74  b b}}.  }.  test
31a0: 5f 6a 6f 69 6e 20 24 74 6e 2e 31 34 20 22 74 32  _join $tn.14 "t2
31b0: 20 4e 41 54 55 52 41 4c 20 43 52 4f 53 53 20 4a   NATURAL CROSS J
31c0: 4f 49 4e 20 74 31 22 20 7b 0a 20 20 20 20 74 32  OIN t1" {.    t2
31d0: 20 74 31 20 2d 75 73 69 6e 67 20 7b 61 20 62 7d   t1 -using {a b}
31e0: 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64 20 7b 74 65   -on {te_and {te
31f0: 5f 65 71 75 61 6c 73 20 61 20 61 7d 20 7b 74 65  _equals a a} {te
3200: 5f 65 71 75 61 6c 73 20 62 20 62 7d 7d 0a 20 20  _equals b b}}.  
3210: 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74  }.  test_join $t
3220: 6e 2e 31 35 20 22 74 32 20 4e 41 54 55 52 41 4c  n.15 "t2 NATURAL
3230: 20 49 4e 4e 45 52 20 4a 4f 49 4e 20 74 31 22 20   INNER JOIN t1" 
3240: 7b 0a 20 20 20 20 74 32 20 74 31 20 2d 75 73 69  {.    t2 t1 -usi
3250: 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65  ng {a b} -on {te
3260: 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73 20  _and {te_equals 
3270: 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20  a a} {te_equals 
3280: 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74  b b}}.  }.  test
3290: 5f 6a 6f 69 6e 20 24 74 6e 2e 31 36 20 22 74 32  _join $tn.16 "t2
32a0: 20 4e 41 54 55 52 41 4c 20 4c 45 46 54 20 4a 4f   NATURAL LEFT JO
32b0: 49 4e 20 74 31 22 20 7b 0a 20 20 20 20 74 32 20  IN t1" {.    t2 
32c0: 74 31 20 2d 6c 65 66 74 20 2d 75 73 69 6e 67 20  t1 -left -using 
32d0: 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e  {a b} -on {te_an
32e0: 64 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61  d {te_equals a a
32f0: 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62  } {te_equals b b
3300: 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f  }}.  }.  test_jo
3310: 69 6e 20 24 74 6e 2e 31 37 20 22 74 32 20 4e 41  in $tn.17 "t2 NA
3320: 54 55 52 41 4c 20 4c 45 46 54 20 4f 55 54 45 52  TURAL LEFT OUTER
3330: 20 4a 4f 49 4e 20 74 31 22 20 7b 0a 20 20 20 20   JOIN t1" {.    
3340: 74 32 20 74 31 20 2d 6c 65 66 74 20 2d 75 73 69  t2 t1 -left -usi
3350: 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65  ng {a b} -on {te
3360: 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73 20  _and {te_equals 
3370: 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20  a a} {te_equals 
3380: 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74  b b}}.  }.  test
3390: 5f 6a 6f 69 6e 20 24 74 6e 2e 31 38 20 22 74 31  _join $tn.18 "t1
33a0: 20 4c 45 46 54 20 4a 4f 49 4e 20 74 32 20 55 53   LEFT JOIN t2 US
33b0: 49 4e 47 20 28 62 29 22 20 7b 0a 20 20 20 20 74  ING (b)" {.    t
33c0: 31 20 74 32 20 2d 6c 65 66 74 20 2d 75 73 69 6e  1 t2 -left -usin
33d0: 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61  g b -on {te_equa
33e0: 6c 73 20 62 20 62 7d 0a 20 20 7d 0a 20 20 74 65  ls b b}.  }.  te
33f0: 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 39 20 22  st_join $tn.19 "
3400: 74 31 20 4a 4f 49 4e 20 74 33 20 55 53 49 4e 47  t1 JOIN t3 USING
3410: 28 62 29 22 20 7b 74 31 20 74 33 20 2d 75 73 69  (b)" {t1 t3 -usi
3420: 6e 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71 75  ng b -on {te_equ
3430: 61 6c 73 20 62 20 62 7d 7d 0a 20 20 74 65 73 74  als b b}}.  test
3440: 5f 6a 6f 69 6e 20 24 74 6e 2e 32 30 20 22 74 33  _join $tn.20 "t3
3450: 20 4a 4f 49 4e 20 74 31 20 55 53 49 4e 47 28 62   JOIN t1 USING(b
3460: 29 22 20 7b 0a 20 20 20 20 74 33 20 74 31 20 2d  )" {.    t3 t1 -
3470: 75 73 69 6e 67 20 62 20 2d 6f 6e 20 7b 74 65 5f  using b -on {te_
3480: 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 62  equals -nocase b
3490: 20 62 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a   b}.  }.  test_j
34a0: 6f 69 6e 20 24 74 6e 2e 32 31 20 22 74 31 20 4e  oin $tn.21 "t1 N
34b0: 41 54 55 52 41 4c 20 4a 4f 49 4e 20 74 33 22 20  ATURAL JOIN t3" 
34c0: 20 7b 0a 20 20 20 20 74 31 20 74 33 20 2d 75 73   {.    t1 t3 -us
34d0: 69 6e 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71  ing b -on {te_eq
34e0: 75 61 6c 73 20 62 20 62 7d 0a 20 20 7d 0a 20 20  uals b b}.  }.  
34f0: 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32 32  test_join $tn.22
3500: 20 22 74 33 20 4e 41 54 55 52 41 4c 20 4a 4f 49   "t3 NATURAL JOI
3510: 4e 20 74 31 22 20 20 7b 0a 20 20 20 20 74 33 20  N t1"  {.    t3 
3520: 74 31 20 2d 75 73 69 6e 67 20 62 20 2d 6f 6e 20  t1 -using b -on 
3530: 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61  {te_equals -noca
3540: 73 65 20 62 20 62 7d 0a 20 20 7d 0a 20 20 74 65  se b b}.  }.  te
3550: 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32 33 20 22  st_join $tn.23 "
3560: 74 31 20 4e 41 54 55 52 41 4c 20 4c 45 46 54 20  t1 NATURAL LEFT 
3570: 4a 4f 49 4e 20 74 33 22 20 7b 0a 20 20 20 20 74  JOIN t3" {.    t
3580: 31 20 74 33 20 2d 6c 65 66 74 20 2d 75 73 69 6e  1 t3 -left -usin
3590: 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61  g b -on {te_equa
35a0: 6c 73 20 62 20 62 7d 0a 20 20 7d 0a 20 20 74 65  ls b b}.  }.  te
35b0: 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32 34 20 22  st_join $tn.24 "
35c0: 74 33 20 4e 41 54 55 52 41 4c 20 4c 45 46 54 20  t3 NATURAL LEFT 
35d0: 4a 4f 49 4e 20 74 31 22 20 7b 0a 20 20 20 20 74  JOIN t1" {.    t
35e0: 33 20 74 31 20 2d 6c 65 66 74 20 2d 75 73 69 6e  3 t1 -left -usin
35f0: 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61  g b -on {te_equa
3600: 6c 73 20 2d 6e 6f 63 61 73 65 20 62 20 62 7d 0a  ls -nocase b b}.
3610: 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20    }.  test_join 
3620: 24 74 6e 2e 32 35 20 22 74 31 20 4c 45 46 54 20  $tn.25 "t1 LEFT 
3630: 4a 4f 49 4e 20 74 33 20 4f 4e 20 28 74 33 2e 62  JOIN t3 ON (t3.b
3640: 3d 74 31 2e 62 29 22 20 7b 0a 20 20 20 20 74 31  =t1.b)" {.    t1
3650: 20 74 33 20 2d 6c 65 66 74 20 2d 6f 6e 20 7b 74   t3 -left -on {t
3660: 65 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65  e_equals -nocase
3670: 20 62 20 62 7d 0a 20 20 7d 0a 20 20 74 65 73 74   b b}.  }.  test
3680: 5f 6a 6f 69 6e 20 24 74 6e 2e 32 36 20 22 74 31  _join $tn.26 "t1
3690: 20 4c 45 46 54 20 4a 4f 49 4e 20 74 33 20 4f 4e   LEFT JOIN t3 ON
36a0: 20 28 74 31 2e 62 3d 74 33 2e 62 29 22 20 7b 0a   (t1.b=t3.b)" {.
36b0: 20 20 20 20 74 31 20 74 33 20 2d 6c 65 66 74 20      t1 t3 -left 
36c0: 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 62  -on {te_equals b
36d0: 20 62 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a   b}.  }.  test_j
36e0: 6f 69 6e 20 24 74 6e 2e 32 37 20 22 74 31 20 4a  oin $tn.27 "t1 J
36f0: 4f 49 4e 20 74 33 20 4f 4e 20 28 74 31 2e 62 3d  OIN t3 ON (t1.b=
3700: 74 33 2e 62 29 22 20 7b 20 74 31 20 74 33 20 2d  t3.b)" { t1 t3 -
3710: 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 62 20  on {te_equals b 
3720: 62 7d 20 7d 0a 0a 20 20 23 20 45 56 49 44 45 4e  b} }..  # EVIDEN
3730: 43 45 2d 4f 46 3a 20 52 2d 32 38 37 36 30 2d 35  CE-OF: R-28760-5
3740: 33 38 34 33 20 57 68 65 6e 20 6d 6f 72 65 20 74  3843 When more t
3750: 68 61 6e 20 74 77 6f 20 74 61 62 6c 65 73 20 61  han two tables a
3760: 72 65 20 6a 6f 69 6e 65 64 0a 20 20 23 20 74 6f  re joined.  # to
3770: 67 65 74 68 65 72 20 61 73 20 70 61 72 74 20 6f  gether as part o
3780: 66 20 61 20 46 52 4f 4d 20 63 6c 61 75 73 65 2c  f a FROM clause,
3790: 20 74 68 65 20 6a 6f 69 6e 20 6f 70 65 72 61 74   the join operat
37a0: 69 6f 6e 73 20 61 72 65 20 70 72 6f 63 65 73 73  ions are process
37b0: 65 64 0a 20 20 23 20 69 6e 20 6f 72 64 65 72 20  ed.  # in order 
37c0: 66 72 6f 6d 20 6c 65 66 74 20 74 6f 20 72 69 67  from left to rig
37d0: 68 74 2e 20 49 6e 20 6f 74 68 65 72 20 77 6f 72  ht. In other wor
37e0: 64 73 2c 20 74 68 65 20 46 52 4f 4d 20 63 6c 61  ds, the FROM cla
37f0: 75 73 65 20 28 41 0a 20 20 23 20 6a 6f 69 6e 2d  use (A.  # join-
3800: 6f 70 2d 31 20 42 20 6a 6f 69 6e 2d 6f 70 2d 32  op-1 B join-op-2
3810: 20 43 29 20 69 73 20 63 6f 6d 70 75 74 65 64 20   C) is computed 
3820: 61 73 20 28 28 41 20 6a 6f 69 6e 2d 6f 70 2d 31  as ((A join-op-1
3830: 20 42 29 20 6a 6f 69 6e 2d 6f 70 2d 32 20 43 29   B) join-op-2 C)
3840: 2e 0a 20 20 23 0a 20 20 23 20 20 20 54 65 73 74  ..  #.  #   Test
3850: 73 20 32 38 61 20 61 6e 64 20 32 38 62 20 73 68  s 28a and 28b sh
3860: 6f 77 20 74 68 61 74 20 74 68 65 20 73 74 61 74  ow that the stat
3870: 65 6d 65 6e 74 20 61 62 6f 76 65 20 69 73 20 74  ement above is t
3880: 72 75 65 20 66 6f 72 20 74 68 69 73 20 63 61 73  rue for this cas
3890: 65 2e 0a 20 20 23 20 20 20 54 65 73 74 20 32 38  e..  #   Test 28
38a0: 63 20 73 68 6f 77 73 20 74 68 61 74 20 69 66 20  c shows that if 
38b0: 74 68 65 20 70 61 72 65 6e 74 68 65 73 69 73 20  the parenthesis 
38c0: 66 6f 72 63 65 20 61 20 64 69 66 66 65 72 65 6e  force a differen
38d0: 74 20 6f 72 64 65 72 20 6f 66 0a 20 20 23 20 20  t order of.  #  
38e0: 20 65 76 61 6c 75 61 74 69 6f 6e 20 74 68 65 20   evaluation the 
38f0: 72 65 73 75 6c 74 20 69 73 20 64 69 66 66 65 72  result is differ
3900: 65 6e 74 2e 20 54 65 73 74 20 32 38 64 20 76 65  ent. Test 28d ve
3910: 72 69 66 69 65 73 20 74 68 61 74 20 74 68 65 20  rifies that the 
3920: 72 65 73 75 6c 74 0a 20 20 23 20 20 20 6f 66 20  result.  #   of 
3930: 74 68 65 20 71 75 65 72 79 20 77 69 74 68 20 74  the query with t
3940: 68 65 20 70 61 72 65 6e 74 68 65 73 69 73 20 66  he parenthesis f
3950: 6f 72 63 69 6e 67 20 61 20 64 69 66 66 65 72 65  orcing a differe
3960: 6e 74 20 6f 72 64 65 72 20 6f 66 20 65 76 61 6c  nt order of eval
3970: 75 61 74 69 6f 6e 0a 20 20 23 20 20 20 69 73 20  uation.  #   is 
3980: 61 73 20 63 61 6c 63 75 6c 61 74 65 64 20 62 79  as calculated by
3990: 20 74 68 65 20 5b 74 65 5f 2a 5d 20 70 72 6f 63   the [te_*] proc
39a0: 73 2e 0a 20 20 23 0a 20 20 73 65 74 20 74 33 5f  s..  #.  set t3_
39b0: 6e 61 74 75 72 61 6c 5f 6c 65 66 74 5f 6a 6f 69  natural_left_joi
39c0: 6e 5f 74 32 20 5b 0a 20 20 20 20 74 65 5f 74 62  n_t2 [.    te_tb
39d0: 6c 6a 6f 69 6e 20 64 62 20 74 33 20 74 32 20 2d  ljoin db t3 t2 -
39e0: 6c 65 66 74 20 2d 75 73 69 6e 67 20 7b 62 7d 20  left -using {b} 
39f0: 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d  -on {te_equals -
3a00: 6e 6f 63 61 73 65 20 62 20 62 7d 0a 20 20 5d 0a  nocase b b}.  ].
3a10: 20 20 73 65 74 20 74 31 20 5b 74 65 5f 72 65 61    set t1 [te_rea
3a20: 64 5f 74 62 6c 20 64 62 20 74 31 5d 0a 20 20 74  d_tbl db t1].  t
3a30: 65 5f 64 61 74 61 73 65 74 5f 65 71 5f 75 6e 6f  e_dataset_eq_uno
3a40: 72 64 65 72 65 64 20 24 74 6e 2e 32 38 61 20 5b  rdered $tn.28a [
3a50: 0a 20 20 20 20 74 65 5f 72 65 61 64 5f 73 71 6c  .    te_read_sql
3a60: 20 64 62 20 22 53 45 4c 45 43 54 20 2a 20 46 52   db "SELECT * FR
3a70: 4f 4d 20 74 33 20 4e 41 54 55 52 41 4c 20 4c 45  OM t3 NATURAL LE
3a80: 46 54 20 4a 4f 49 4e 20 74 32 20 4e 41 54 55 52  FT JOIN t2 NATUR
3a90: 41 4c 20 4a 4f 49 4e 20 74 31 22 0a 20 20 5d 20  AL JOIN t1".  ] 
3aa0: 5b 74 65 5f 6a 6f 69 6e 20 24 74 33 5f 6e 61 74  [te_join $t3_nat
3ab0: 75 72 61 6c 5f 6c 65 66 74 5f 6a 6f 69 6e 5f 74  ural_left_join_t
3ac0: 32 20 24 74 31 20 20 20 20 20 20 20 20 20 20 20  2 $t1           
3ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3ae0: 20 20 20 20 20 5c 0a 20 20 20 20 20 20 2d 75 73       \.      -us
3af0: 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74  ing {a b} -on {t
3b00: 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73  e_and {te_equals
3b10: 20 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73   a a} {te_equals
3b20: 20 2d 6e 6f 63 61 73 65 20 62 20 62 7d 7d 20 20   -nocase b b}}  
3b30: 5c 0a 20 20 5d 0a 0a 20 20 74 65 5f 64 61 74 61  \.  ]..  te_data
3b40: 73 65 74 5f 65 71 5f 75 6e 6f 72 64 65 72 65 64  set_eq_unordered
3b50: 20 24 74 6e 2e 32 38 62 20 5b 0a 20 20 20 20 74   $tn.28b [.    t
3b60: 65 5f 72 65 61 64 5f 73 71 6c 20 64 62 20 22 53  e_read_sql db "S
3b70: 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 28 74 33  ELECT * FROM (t3
3b80: 20 4e 41 54 55 52 41 4c 20 4c 45 46 54 20 4a 4f   NATURAL LEFT JO
3b90: 49 4e 20 74 32 29 20 4e 41 54 55 52 41 4c 20 4a  IN t2) NATURAL J
3ba0: 4f 49 4e 20 74 31 22 0a 20 20 5d 20 5b 74 65 5f  OIN t1".  ] [te_
3bb0: 6a 6f 69 6e 20 24 74 33 5f 6e 61 74 75 72 61 6c  join $t3_natural
3bc0: 5f 6c 65 66 74 5f 6a 6f 69 6e 5f 74 32 20 24 74  _left_join_t2 $t
3bd0: 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1               
3be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3bf0: 20 5c 0a 20 20 20 20 20 20 2d 75 73 69 6e 67 20   \.      -using 
3c00: 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e  {a b} -on {te_an
3c10: 64 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61  d {te_equals a a
3c20: 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e 6f  } {te_equals -no
3c30: 63 61 73 65 20 62 20 62 7d 7d 20 20 5c 0a 20 20  case b b}}  \.  
3c40: 5d 0a 0a 20 20 74 65 5f 64 61 74 61 73 65 74 5f  ]..  te_dataset_
3c50: 6e 65 5f 75 6e 6f 72 64 65 72 65 64 20 24 74 6e  ne_unordered $tn
3c60: 2e 32 38 63 20 5b 0a 20 20 20 20 74 65 5f 72 65  .28c [.    te_re
3c70: 61 64 5f 73 71 6c 20 64 62 20 22 53 45 4c 45 43  ad_sql db "SELEC
3c80: 54 20 2a 20 46 52 4f 4d 20 28 74 33 20 4e 41 54  T * FROM (t3 NAT
3c90: 55 52 41 4c 20 4c 45 46 54 20 4a 4f 49 4e 20 74  URAL LEFT JOIN t
3ca0: 32 29 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20  2) NATURAL JOIN 
3cb0: 74 31 22 0a 20 20 5d 20 5b 0a 20 20 20 20 74 65  t1".  ] [.    te
3cc0: 5f 72 65 61 64 5f 73 71 6c 20 64 62 20 22 53 45  _read_sql db "SE
3cd0: 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74 33 20 4e  LECT * FROM t3 N
3ce0: 41 54 55 52 41 4c 20 4c 45 46 54 20 4a 4f 49 4e  ATURAL LEFT JOIN
3cf0: 20 28 74 32 20 4e 41 54 55 52 41 4c 20 4a 4f 49   (t2 NATURAL JOI
3d00: 4e 20 74 31 29 22 0a 20 20 5d 0a 0a 20 20 73 65  N t1)".  ]..  se
3d10: 74 20 74 32 5f 6e 61 74 75 72 61 6c 5f 6a 6f 69  t t2_natural_joi
3d20: 6e 5f 74 31 20 5b 74 65 5f 74 62 6c 6a 6f 69 6e  n_t1 [te_tbljoin
3d30: 20 64 62 20 74 32 20 74 31 20 2d 75 73 69 6e 67   db t2 t1 -using
3d40: 20 7b 61 20 62 7d 20 20 20 20 20 20 20 20 20 20   {a b}          
3d50: 20 20 20 20 20 20 20 5c 0a 20 20 20 20 20 20 20         \.       
3d60: 20 2d 75 73 69 6e 67 20 7b 61 20 62 7d 20 2d 6f   -using {a b} -o
3d70: 6e 20 7b 74 65 5f 61 6e 64 20 7b 74 65 5f 65 71  n {te_and {te_eq
3d80: 75 61 6c 73 20 61 20 61 7d 20 7b 74 65 5f 65 71  uals a a} {te_eq
3d90: 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 62 20 62  uals -nocase b b
3da0: 7d 7d 20 20 5c 0a 20 20 5d 0a 20 20 73 65 74 20  }}  \.  ].  set 
3db0: 74 33 20 5b 74 65 5f 72 65 61 64 5f 74 62 6c 20  t3 [te_read_tbl 
3dc0: 64 62 20 74 33 5d 0a 20 20 74 65 5f 64 61 74 61  db t3].  te_data
3dd0: 73 65 74 5f 65 71 5f 75 6e 6f 72 64 65 72 65 64  set_eq_unordered
3de0: 20 24 74 6e 2e 32 38 64 20 5b 0a 20 20 20 20 74   $tn.28d [.    t
3df0: 65 5f 72 65 61 64 5f 73 71 6c 20 64 62 20 22 53  e_read_sql db "S
3e00: 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74 33 20  ELECT * FROM t3 
3e10: 4e 41 54 55 52 41 4c 20 4c 45 46 54 20 4a 4f 49  NATURAL LEFT JOI
3e20: 4e 20 28 74 32 20 4e 41 54 55 52 41 4c 20 4a 4f  N (t2 NATURAL JO
3e30: 49 4e 20 74 31 29 22 0a 20 20 5d 20 5b 74 65 5f  IN t1)".  ] [te_
3e40: 6a 6f 69 6e 20 24 74 33 20 24 74 32 5f 6e 61 74  join $t3 $t2_nat
3e50: 75 72 61 6c 5f 6a 6f 69 6e 5f 74 31 20 20 20 20  ural_join_t1    
3e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3e80: 20 20 20 5c 0a 20 20 20 20 20 20 2d 6c 65 66 74     \.      -left
3e90: 20 2d 75 73 69 6e 67 20 7b 62 7d 20 2d 6f 6e 20   -using {b} -on 
3ea0: 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61  {te_equals -noca
3eb0: 73 65 20 62 20 62 7d 20 20 20 20 20 20 20 20 20  se b b}         
3ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3ed0: 5c 0a 20 20 5d 0a 7d 0a 0a 64 6f 5f 65 78 65 63  \.  ].}..do_exec
3ee0: 73 71 6c 5f 74 65 73 74 20 65 5f 73 65 6c 65 63  sql_test e_selec
3ef0: 74 2d 32 2e 32 2e 30 20 7b 0a 20 20 43 52 45 41  t-2.2.0 {.  CREA
3f00: 54 45 20 54 41 42 4c 45 20 74 34 28 78 20 54 45  TE TABLE t4(x TE
3f10: 58 54 20 43 4f 4c 4c 41 54 45 20 6e 6f 63 61 73  XT COLLATE nocas
3f20: 65 29 3b 0a 20 20 43 52 45 41 54 45 20 54 41 42  e);.  CREATE TAB
3f30: 4c 45 20 74 35 28 79 20 49 4e 54 45 47 45 52 2c  LE t5(y INTEGER,
3f40: 20 7a 20 54 45 58 54 20 43 4f 4c 4c 41 54 45 20   z TEXT COLLATE 
3f50: 62 69 6e 61 72 79 29 3b 0a 0a 20 20 49 4e 53 45  binary);..  INSE
3f60: 52 54 20 49 4e 54 4f 20 74 34 20 56 41 4c 55 45  RT INTO t4 VALUE
3f70: 53 28 27 32 2e 30 27 29 3b 0a 20 20 49 4e 53 45  S('2.0');.  INSE
3f80: 52 54 20 49 4e 54 4f 20 74 34 20 56 41 4c 55 45  RT INTO t4 VALUE
3f90: 53 28 27 54 57 4f 27 29 3b 0a 20 20 49 4e 53 45  S('TWO');.  INSE
3fa0: 52 54 20 49 4e 54 4f 20 74 35 20 56 41 4c 55 45  RT INTO t5 VALUE
3fb0: 53 28 32 2c 20 27 74 77 6f 27 29 3b 0a 7d 20 7b  S(2, 'two');.} {
3fc0: 7d 0a 0a 23 20 45 56 49 44 45 4e 43 45 2d 4f 46  }..# EVIDENCE-OF
3fd0: 3a 20 52 2d 35 39 32 33 37 2d 34 36 37 34 32 20  : R-59237-46742 
3fe0: 41 20 73 75 62 71 75 65 72 79 20 73 70 65 63 69  A subquery speci
3ff0: 66 69 65 64 20 69 6e 20 74 68 65 0a 23 20 74 61  fied in the.# ta
4000: 62 6c 65 2d 6f 72 2d 73 75 62 71 75 65 72 79 20  ble-or-subquery 
4010: 66 6f 6c 6c 6f 77 69 6e 67 20 74 68 65 20 46 52  following the FR
4020: 4f 4d 20 63 6c 61 75 73 65 20 69 6e 20 61 20 73  OM clause in a s
4030: 69 6d 70 6c 65 20 53 45 4c 45 43 54 0a 23 20 73  imple SELECT.# s
4040: 74 61 74 65 6d 65 6e 74 20 69 73 20 68 61 6e 64  tatement is hand
4050: 6c 65 64 20 61 73 20 69 66 20 69 74 20 77 61 73  led as if it was
4060: 20 61 20 74 61 62 6c 65 20 63 6f 6e 74 61 69 6e   a table contain
4070: 69 6e 67 20 74 68 65 20 64 61 74 61 20 72 65 74  ing the data ret
4080: 75 72 6e 65 64 0a 23 20 62 79 20 65 78 65 63 75  urned.# by execu
4090: 74 69 6e 67 20 74 68 65 20 73 75 62 71 75 65 72  ting the subquer
40a0: 79 20 73 74 61 74 65 6d 65 6e 74 2e 0a 23 0a 23  y statement..#.#
40b0: 20 45 56 49 44 45 4e 43 45 2d 4f 46 3a 20 52 2d   EVIDENCE-OF: R-
40c0: 32 37 34 33 38 2d 35 33 35 35 38 20 45 61 63 68  27438-53558 Each
40d0: 20 63 6f 6c 75 6d 6e 20 6f 66 20 74 68 65 20 73   column of the s
40e0: 75 62 71 75 65 72 79 20 68 61 73 20 74 68 65 0a  ubquery has the.
40f0: 23 20 63 6f 6c 6c 61 74 69 6f 6e 20 73 65 71 75  # collation sequ
4100: 65 6e 63 65 20 61 6e 64 20 61 66 66 69 6e 69 74  ence and affinit
4110: 79 20 6f 66 20 74 68 65 20 63 6f 72 72 65 73 70  y of the corresp
4120: 6f 6e 64 69 6e 67 20 65 78 70 72 65 73 73 69 6f  onding expressio
4130: 6e 20 69 6e 20 74 68 65 0a 23 20 73 75 62 71 75  n in the.# subqu
4140: 65 72 79 20 73 74 61 74 65 6d 65 6e 74 2e 0a 23  ery statement..#
4150: 0a 66 6f 72 65 61 63 68 20 7b 74 6e 20 73 75 62  .foreach {tn sub
4160: 73 65 6c 65 63 74 20 73 65 6c 65 63 74 20 73 70  select select sp
4170: 65 63 7d 20 7b 0a 20 20 31 20 20 20 22 53 45 4c  ec} {.  1   "SEL
4180: 45 43 54 20 2a 20 46 52 4f 4d 20 74 32 22 20 20  ECT * FROM t2"  
4190: 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20   "SELECT * FROM 
41a0: 74 31 20 4a 4f 49 4e 20 25 73 73 25 22 20 0a 20  t1 JOIN %ss%" . 
41b0: 20 20 20 20 20 7b 74 31 20 25 73 73 25 7d 0a 0a       {t1 %ss%}..
41c0: 20 20 32 20 20 20 22 53 45 4c 45 43 54 20 2a 20    2   "SELECT * 
41d0: 46 52 4f 4d 20 74 32 22 20 20 20 22 53 45 4c 45  FROM t2"   "SELE
41e0: 43 54 20 2a 20 46 52 4f 4d 20 74 31 20 4a 4f 49  CT * FROM t1 JOI
41f0: 4e 20 25 73 73 25 20 41 53 20 78 20 4f 4e 20 28  N %ss% AS x ON (
4200: 74 31 2e 61 3d 78 2e 61 29 22 20 0a 20 20 20 20  t1.a=x.a)" .    
4210: 20 20 7b 74 31 20 25 73 73 25 20 2d 6f 6e 20 7b    {t1 %ss% -on {
4220: 74 65 5f 65 71 75 61 6c 73 20 30 20 30 7d 7d 0a  te_equals 0 0}}.
4230: 0a 20 20 33 20 20 20 22 53 45 4c 45 43 54 20 2a  .  3   "SELECT *
4240: 20 46 52 4f 4d 20 74 32 22 20 20 20 22 53 45 4c   FROM t2"   "SEL
4250: 45 43 54 20 2a 20 46 52 4f 4d 20 25 73 73 25 20  ECT * FROM %ss% 
4260: 41 53 20 78 20 4a 4f 49 4e 20 74 31 20 4f 4e 20  AS x JOIN t1 ON 
4270: 28 74 31 2e 61 3d 78 2e 61 29 22 20 0a 20 20 20  (t1.a=x.a)" .   
4280: 20 20 20 7b 25 73 73 25 20 74 31 20 2d 6f 6e 20     {%ss% t1 -on 
4290: 7b 74 65 5f 65 71 75 61 6c 73 20 30 20 30 7d 7d  {te_equals 0 0}}
42a0: 0a 0a 20 20 34 20 20 20 22 53 45 4c 45 43 54 20  ..  4   "SELECT 
42b0: 2a 20 46 52 4f 4d 20 74 31 2c 20 74 32 22 20 22  * FROM t1, t2" "
42c0: 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 25 73  SELECT * FROM %s
42d0: 73 25 20 41 53 20 78 20 4a 4f 49 4e 20 74 33 22  s% AS x JOIN t3"
42e0: 0a 20 20 20 20 20 20 7b 25 73 73 25 20 74 33 7d  .      {%ss% t3}
42f0: 0a 0a 20 20 35 20 20 20 22 53 45 4c 45 43 54 20  ..  5   "SELECT 
4300: 2a 20 46 52 4f 4d 20 74 31 2c 20 74 32 22 20 22  * FROM t1, t2" "
4310: 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 25 73  SELECT * FROM %s
4320: 73 25 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20  s% NATURAL JOIN 
4330: 74 33 22 0a 20 20 20 20 20 20 7b 25 73 73 25 20  t3".      {%ss% 
4340: 74 33 20 2d 75 73 69 6e 67 20 62 20 2d 6f 6e 20  t3 -using b -on 
4350: 7b 74 65 5f 65 71 75 61 6c 73 20 31 20 30 7d 7d  {te_equals 1 0}}
4360: 0a 0a 20 20 36 20 20 20 22 53 45 4c 45 43 54 20  ..  6   "SELECT 
4370: 2a 20 46 52 4f 4d 20 74 31 2c 20 74 32 22 20 22  * FROM t1, t2" "
4380: 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74 33  SELECT * FROM t3
4390: 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20 25 73   NATURAL JOIN %s
43a0: 73 25 22 0a 20 20 20 20 20 20 7b 74 33 20 25 73  s%".      {t3 %s
43b0: 73 25 20 2d 75 73 69 6e 67 20 62 20 2d 6f 6e 20  s% -using b -on 
43c0: 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61  {te_equals -noca
43d0: 73 65 20 30 20 31 7d 7d 0a 0a 20 20 37 20 20 20  se 0 1}}..  7   
43e0: 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74  "SELECT * FROM t
43f0: 31 2c 20 74 32 22 20 22 53 45 4c 45 43 54 20 2a  1, t2" "SELECT *
4400: 20 46 52 4f 4d 20 74 33 20 4e 41 54 55 52 41 4c   FROM t3 NATURAL
4410: 20 4c 45 46 54 20 4a 4f 49 4e 20 25 73 73 25 22   LEFT JOIN %ss%"
4420: 0a 20 20 20 20 20 20 7b 74 33 20 25 73 73 25 20  .      {t3 %ss% 
4430: 2d 6c 65 66 74 20 2d 75 73 69 6e 67 20 62 20 2d  -left -using b -
4440: 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e  on {te_equals -n
4450: 6f 63 61 73 65 20 30 20 31 7d 7d 0a 0a 20 20 38  ocase 0 1}}..  8
4460: 20 20 20 22 53 45 4c 45 43 54 20 63 6f 75 6e 74     "SELECT count
4470: 28 2a 29 20 41 53 20 79 20 46 52 4f 4d 20 74 34  (*) AS y FROM t4
4480: 22 20 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52  "   "SELECT * FR
4490: 4f 4d 20 74 35 2c 20 25 73 73 25 20 55 53 49 4e  OM t5, %ss% USIN
44a0: 47 20 28 79 29 22 0a 20 20 20 20 20 20 7b 74 35  G (y)".      {t5
44b0: 20 25 73 73 25 20 2d 75 73 69 6e 67 20 79 20 2d   %ss% -using y -
44c0: 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d 61  on {te_equals -a
44d0: 66 66 69 6e 69 74 79 20 74 65 78 74 20 30 20 30  ffinity text 0 0
44e0: 7d 7d 0a 0a 20 20 39 20 20 20 22 53 45 4c 45 43  }}..  9   "SELEC
44f0: 54 20 63 6f 75 6e 74 28 2a 29 20 41 53 20 79 20  T count(*) AS y 
4500: 46 52 4f 4d 20 74 34 22 20 20 20 22 53 45 4c 45  FROM t4"   "SELE
4510: 43 54 20 2a 20 46 52 4f 4d 20 25 73 73 25 2c 20  CT * FROM %ss%, 
4520: 74 35 20 55 53 49 4e 47 20 28 79 29 22 0a 20 20  t5 USING (y)".  
4530: 20 20 20 20 7b 25 73 73 25 20 74 35 20 2d 75 73      {%ss% t5 -us
4540: 69 6e 67 20 79 20 2d 6f 6e 20 7b 74 65 5f 65 71  ing y -on {te_eq
4550: 75 61 6c 73 20 2d 61 66 66 69 6e 69 74 79 20 74  uals -affinity t
4560: 65 78 74 20 30 20 30 7d 7d 0a 0a 20 20 31 30 20  ext 0 0}}..  10 
4570: 20 22 53 45 4c 45 43 54 20 78 20 41 53 20 79 20   "SELECT x AS y 
4580: 46 52 4f 4d 20 74 34 22 20 20 20 22 53 45 4c 45  FROM t4"   "SELE
4590: 43 54 20 2a 20 46 52 4f 4d 20 25 73 73 25 20 4a  CT * FROM %ss% J
45a0: 4f 49 4e 20 74 35 20 55 53 49 4e 47 20 28 79 29  OIN t5 USING (y)
45b0: 22 0a 20 20 20 20 20 20 7b 25 73 73 25 20 74 35  ".      {%ss% t5
45c0: 20 2d 75 73 69 6e 67 20 79 20 2d 6f 6e 20 7b 74   -using y -on {t
45d0: 65 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65  e_equals -nocase
45e0: 20 2d 61 66 66 69 6e 69 74 79 20 69 6e 74 65 67   -affinity integ
45f0: 65 72 20 30 20 30 7d 7d 0a 0a 20 20 31 31 20 20  er 0 0}}..  11  
4600: 22 53 45 4c 45 43 54 20 78 20 41 53 20 79 20 46  "SELECT x AS y F
4610: 52 4f 4d 20 74 34 22 20 20 20 22 53 45 4c 45 43  ROM t4"   "SELEC
4620: 54 20 2a 20 46 52 4f 4d 20 74 35 20 4a 4f 49 4e  T * FROM t5 JOIN
4630: 20 25 73 73 25 20 55 53 49 4e 47 20 28 79 29 22   %ss% USING (y)"
4640: 0a 20 20 20 20 20 20 7b 74 35 20 25 73 73 25 20  .      {t5 %ss% 
4650: 2d 75 73 69 6e 67 20 79 20 2d 6f 6e 20 7b 74 65  -using y -on {te
4660: 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20  _equals -nocase 
4670: 2d 61 66 66 69 6e 69 74 79 20 69 6e 74 65 67 65  -affinity intege
4680: 72 20 30 20 30 7d 7d 0a 0a 20 20 31 32 20 20 22  r 0 0}}..  12  "
4690: 53 45 4c 45 43 54 20 79 20 41 53 20 78 20 46 52  SELECT y AS x FR
46a0: 4f 4d 20 74 35 22 20 20 20 22 53 45 4c 45 43 54  OM t5"   "SELECT
46b0: 20 2a 20 46 52 4f 4d 20 25 73 73 25 20 4a 4f 49   * FROM %ss% JOI
46c0: 4e 20 74 34 20 55 53 49 4e 47 20 28 78 29 22 0a  N t4 USING (x)".
46d0: 20 20 20 20 20 20 7b 25 73 73 25 20 74 34 20 2d        {%ss% t4 -
46e0: 75 73 69 6e 67 20 78 20 2d 6f 6e 20 7b 74 65 5f  using x -on {te_
46f0: 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 2d  equals -nocase -
4700: 61 66 66 69 6e 69 74 79 20 69 6e 74 65 67 65 72  affinity integer
4710: 20 30 20 30 7d 7d 0a 0a 20 20 31 33 20 20 22 53   0 0}}..  13  "S
4720: 45 4c 45 43 54 20 79 20 41 53 20 78 20 46 52 4f  ELECT y AS x FRO
4730: 4d 20 74 35 22 20 20 20 22 53 45 4c 45 43 54 20  M t5"   "SELECT 
4740: 2a 20 46 52 4f 4d 20 74 34 20 4a 4f 49 4e 20 25  * FROM t4 JOIN %
4750: 73 73 25 20 55 53 49 4e 47 20 28 78 29 22 0a 20  ss% USING (x)". 
4760: 20 20 20 20 20 7b 74 34 20 25 73 73 25 20 2d 75       {t4 %ss% -u
4770: 73 69 6e 67 20 78 20 2d 6f 6e 20 7b 74 65 5f 65  sing x -on {te_e
4780: 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 2d 61  quals -nocase -a
4790: 66 66 69 6e 69 74 79 20 69 6e 74 65 67 65 72 20  ffinity integer 
47a0: 30 20 30 7d 7d 0a 0a 20 20 31 34 20 20 22 53 45  0 0}}..  14  "SE
47b0: 4c 45 43 54 20 2b 79 20 41 53 20 78 20 46 52 4f  LECT +y AS x FRO
47c0: 4d 20 74 35 22 20 20 20 22 53 45 4c 45 43 54 20  M t5"   "SELECT 
47d0: 2a 20 46 52 4f 4d 20 25 73 73 25 20 4a 4f 49 4e  * FROM %ss% JOIN
47e0: 20 74 34 20 55 53 49 4e 47 20 28 78 29 22 0a 20   t4 USING (x)". 
47f0: 20 20 20 20 20 7b 25 73 73 25 20 74 34 20 2d 75       {%ss% t4 -u
4800: 73 69 6e 67 20 78 20 2d 6f 6e 20 7b 74 65 5f 65  sing x -on {te_e
4810: 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 2d 61  quals -nocase -a
4820: 66 66 69 6e 69 74 79 20 74 65 78 74 20 30 20 30  ffinity text 0 0
4830: 7d 7d 0a 0a 20 20 31 35 20 20 22 53 45 4c 45 43  }}..  15  "SELEC
4840: 54 20 2b 79 20 41 53 20 78 20 46 52 4f 4d 20 74  T +y AS x FROM t
4850: 35 22 20 20 20 22 53 45 4c 45 43 54 20 2a 20 46  5"   "SELECT * F
4860: 52 4f 4d 20 74 34 20 4a 4f 49 4e 20 25 73 73 25  ROM t4 JOIN %ss%
4870: 20 55 53 49 4e 47 20 28 78 29 22 0a 20 20 20 20   USING (x)".    
4880: 20 20 7b 74 34 20 25 73 73 25 20 2d 75 73 69 6e    {t4 %ss% -usin
4890: 67 20 78 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61  g x -on {te_equa
48a0: 6c 73 20 2d 6e 6f 63 61 73 65 20 2d 61 66 66 69  ls -nocase -affi
48b0: 6e 69 74 79 20 74 65 78 74 20 30 20 30 7d 7d 0a  nity text 0 0}}.
48c0: 7d 20 7b 0a 0a 20 20 23 20 43 72 65 61 74 65 20  } {..  # Create 
48d0: 61 20 74 65 6d 70 6f 72 61 72 79 20 74 61 62 6c  a temporary tabl
48e0: 65 20 6e 61 6d 65 64 20 25 73 73 25 20 63 6f 6e  e named %ss% con
48f0: 74 61 69 6e 69 6e 67 20 74 68 65 20 64 61 74 61  taining the data
4900: 20 72 65 74 75 72 6e 65 64 20 62 79 0a 20 20 23   returned by.  #
4910: 20 74 68 65 20 73 75 62 2d 73 65 6c 65 63 74 2e   the sub-select.
4920: 20 54 68 65 6e 20 68 61 76 65 20 74 68 65 20 5b   Then have the [
4930: 74 65 5f 74 62 6c 6a 6f 69 6e 5d 20 70 72 6f 63  te_tbljoin] proc
4940: 20 75 73 65 20 74 68 69 73 20 74 61 62 6c 65 20   use this table 
4950: 74 6f 0a 20 20 23 20 63 6f 6d 70 75 74 65 20 74  to.  # compute t
4960: 68 65 20 65 78 70 65 63 74 65 64 20 72 65 73 75  he expected resu
4970: 6c 74 73 20 6f 66 20 74 68 65 20 24 73 65 6c 65  lts of the $sele
4980: 63 74 20 71 75 65 72 79 2e 20 44 72 6f 70 20 74  ct query. Drop t
4990: 68 65 20 74 65 6d 70 6f 72 61 72 79 0a 20 20 23  he temporary.  #
49a0: 20 74 61 62 6c 65 20 62 65 66 6f 72 65 20 63 6f   table before co
49b0: 6e 74 69 6e 75 69 6e 67 2e 0a 20 20 23 0a 20 20  ntinuing..  #.  
49c0: 65 78 65 63 73 71 6c 20 22 43 52 45 41 54 45 20  execsql "CREATE 
49d0: 54 45 4d 50 20 54 41 42 4c 45 20 27 25 73 73 25  TEMP TABLE '%ss%
49e0: 27 20 41 53 20 24 73 75 62 73 65 6c 65 63 74 22  ' AS $subselect"
49f0: 0a 20 20 73 65 74 20 74 65 20 5b 65 76 61 6c 20  .  set te [eval 
4a00: 74 65 5f 74 62 6c 6a 6f 69 6e 20 64 62 20 24 73  te_tbljoin db $s
4a10: 70 65 63 5d 0a 20 20 65 78 65 63 73 71 6c 20 22  pec].  execsql "
4a20: 44 52 4f 50 20 54 41 42 4c 45 20 27 25 73 73 25  DROP TABLE '%ss%
4a30: 27 22 0a 0a 20 20 23 20 43 68 65 63 6b 20 74 68  '"..  # Check th
4a40: 61 74 20 74 68 65 20 61 63 74 75 61 6c 20 64 61  at the actual da
4a50: 74 61 20 72 65 74 75 72 6e 65 64 20 62 79 20 74  ta returned by t
4a60: 68 65 20 24 73 65 6c 65 63 74 20 71 75 65 72 79  he $select query
4a70: 20 69 73 20 74 68 65 20 73 61 6d 65 0a 20 20 23   is the same.  #
4a80: 20 61 73 20 74 68 65 20 65 78 70 65 63 74 65 64   as the expected
4a90: 20 64 61 74 61 20 63 61 6c 63 75 6c 61 74 65 64   data calculated
4aa0: 20 75 73 69 6e 67 20 5b 74 65 5f 74 62 6c 6a 6f   using [te_tbljo
4ab0: 69 6e 5d 20 61 62 6f 76 65 2e 0a 20 20 23 0a 20  in] above..  #. 
4ac0: 20 74 65 5f 64 61 74 61 73 65 74 5f 65 71 5f 75   te_dataset_eq_u
4ad0: 6e 6f 72 64 65 72 65 64 20 65 5f 73 65 6c 65 63  nordered e_selec
4ae0: 74 2d 32 2e 32 2e 31 2e 24 74 6e 20 5b 0a 20 20  t-2.2.1.$tn [.  
4af0: 20 20 74 65 5f 72 65 61 64 5f 73 71 6c 20 64 62    te_read_sql db
4b00: 20 5b 73 74 72 69 6e 67 20 6d 61 70 20 5b 6c 69   [string map [li
4b10: 73 74 20 25 73 73 25 20 22 28 24 73 75 62 73 65  st %ss% "($subse
4b20: 6c 65 63 74 29 22 5d 20 24 73 65 6c 65 63 74 5d  lect)"] $select]
4b30: 0a 20 20 5d 20 24 74 65 0a 7d 0a 0a 66 69 6e 69  .  ] $te.}..fini
4b40: 73 68 5f 74 65 73 74 0a                          sh_test.