SQLite4
Hex Artifact Content
Not logged in

Artifact 11668fe27ef9ceac44243fd2bae96cddffaaff2a:


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 34 5f 70 72 65  t S [sqlite4_pre
0f60: 70 61 72 65 20 24 64 62 20 24 73 71 6c 20 2d 31  pare $db $sql -1
0f70: 20 44 55 4d 4d 59 5d 0a 0a 20 20 73 65 74 20 63   DUMMY]..  set c
0f80: 6f 6c 73 20 5b 6c 69 73 74 5d 0a 20 20 66 6f 72  ols [list].  for
0f90: 20 7b 73 65 74 20 69 20 30 7d 20 7b 24 69 20 3c   {set i 0} {$i <
0fa0: 20 5b 73 71 6c 69 74 65 34 5f 63 6f 6c 75 6d 6e   [sqlite4_column
0fb0: 5f 63 6f 75 6e 74 20 24 53 5d 7d 20 7b 69 6e 63  _count $S]} {inc
0fc0: 72 20 69 7d 20 7b 0a 20 20 20 20 6c 61 70 70 65  r i} {.    lappe
0fd0: 6e 64 20 63 6f 6c 73 20 5b 73 71 6c 69 74 65 34  nd cols [sqlite4
0fe0: 5f 63 6f 6c 75 6d 6e 5f 6e 61 6d 65 20 24 53 20  _column_name $S 
0ff0: 24 69 5d 0a 20 20 7d 0a 0a 20 20 73 65 74 20 72  $i].  }..  set r
1000: 6f 77 73 20 5b 6c 69 73 74 5d 0a 20 20 77 68 69  ows [list].  whi
1010: 6c 65 20 7b 5b 73 71 6c 69 74 65 34 5f 73 74 65  le {[sqlite4_ste
1020: 70 20 24 53 5d 20 3d 3d 20 22 53 51 4c 49 54 45  p $S] == "SQLITE
1030: 34 5f 52 4f 57 22 7d 20 7b 0a 20 20 20 20 73 65  4_ROW"} {.    se
1040: 74 20 72 20 5b 6c 69 73 74 5d 0a 20 20 20 20 66  t r [list].    f
1050: 6f 72 20 7b 73 65 74 20 69 20 30 7d 20 7b 24 69  or {set i 0} {$i
1060: 20 3c 20 5b 73 71 6c 69 74 65 34 5f 63 6f 6c 75   < [sqlite4_colu
1070: 6d 6e 5f 63 6f 75 6e 74 20 24 53 5d 7d 20 7b 69  mn_count $S]} {i
1080: 6e 63 72 20 69 7d 20 7b 0a 20 20 20 20 20 20 6c  ncr i} {.      l
1090: 61 70 70 65 6e 64 20 72 20 5b 6c 69 73 74 20 5b  append r [list [
10a0: 73 71 6c 69 74 65 34 5f 63 6f 6c 75 6d 6e 5f 74  sqlite4_column_t
10b0: 79 70 65 20 24 53 20 24 69 5d 20 5b 73 71 6c 69  ype $S $i] [sqli
10c0: 74 65 34 5f 63 6f 6c 75 6d 6e 5f 74 65 78 74 20  te4_column_text 
10d0: 24 53 20 24 69 5d 5d 0a 20 20 20 20 7d 0a 20 20  $S $i]].    }.  
10e0: 20 20 6c 61 70 70 65 6e 64 20 72 6f 77 73 20 24    lappend rows $
10f0: 72 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 34 5f  r.  }.  sqlite4_
1100: 66 69 6e 61 6c 69 7a 65 20 24 53 0a 0a 20 20 72  finalize $S..  r
1110: 65 74 75 72 6e 20 5b 6c 69 73 74 20 24 63 6f 6c  eturn [list $col
1120: 73 20 24 72 6f 77 73 5d 0a 7d 0a 0a 23 2d 2d 2d  s $rows].}..#---
1130: 2d 2d 2d 2d 0a 23 20 55 73 61 67 65 3a 20 20 20  ----.# Usage:   
1140: 74 65 5f 6a 6f 69 6e 20 3c 74 61 62 6c 65 2d 64  te_join <table-d
1150: 61 74 61 31 3e 20 3c 74 61 62 6c 65 2d 64 61 74  ata1> <table-dat
1160: 61 32 3e 20 3c 6a 6f 69 6e 20 73 70 65 63 3e 2e  a2> <join spec>.
1170: 2e 2e 0a 23 0a 23 20 57 68 65 72 65 20 61 20 6a  ...#.# Where a j
1180: 6f 69 6e 2d 73 70 65 63 20 69 73 20 61 6e 20 6f  oin-spec is an o
1190: 70 74 69 6f 6e 61 6c 20 6c 69 73 74 20 6f 66 20  ptional list of 
11a0: 61 72 67 75 6d 65 6e 74 73 20 61 73 20 66 6f 6c  arguments as fol
11b0: 6c 6f 77 73 3a 0a 23 0a 23 20 20 20 3f 2d 6c 65  lows:.#.#   ?-le
11c0: 66 74 3f 0a 23 20 20 20 3f 2d 75 73 69 6e 67 20  ft?.#   ?-using 
11d0: 63 6f 6c 6e 61 6d 65 2d 6c 69 73 74 3f 0a 23 20  colname-list?.# 
11e0: 20 20 3f 2d 6f 6e 20 6f 6e 2d 65 78 70 72 2d 70    ?-on on-expr-p
11f0: 72 6f 63 3f 0a 23 0a 70 72 6f 63 20 74 65 5f 6a  roc?.#.proc te_j
1200: 6f 69 6e 20 7b 64 61 74 61 31 20 64 61 74 61 32  oin {data1 data2
1210: 20 61 72 67 73 7d 20 7b 0a 0a 20 20 73 65 74 20   args} {..  set 
1220: 74 65 73 74 70 72 6f 63 20 22 22 0a 20 20 73 65  testproc "".  se
1230: 74 20 75 73 69 6e 67 6c 69 73 74 20 5b 6c 69 73  t usinglist [lis
1240: 74 5d 0a 20 20 73 65 74 20 69 73 6c 65 66 74 20  t].  set isleft 
1250: 30 0a 20 20 66 6f 72 20 7b 73 65 74 20 69 20 30  0.  for {set i 0
1260: 7d 20 7b 24 69 20 3c 20 5b 6c 6c 65 6e 67 74 68  } {$i < [llength
1270: 20 24 61 72 67 73 5d 7d 20 7b 69 6e 63 72 20 69   $args]} {incr i
1280: 7d 20 7b 0a 20 20 20 20 73 65 74 20 61 20 5b 6c  } {.    set a [l
1290: 69 6e 64 65 78 20 24 61 72 67 73 20 24 69 5d 0a  index $args $i].
12a0: 20 20 20 20 73 77 69 74 63 68 20 2d 2d 20 24 61      switch -- $a
12b0: 20 7b 0a 20 20 20 20 20 20 2d 6f 6e 20 20 20 20   {.      -on    
12c0: 20 7b 20 73 65 74 20 74 65 73 74 70 72 6f 63 20   { set testproc 
12d0: 5b 6c 69 6e 64 65 78 20 24 61 72 67 73 20 5b 69  [lindex $args [i
12e0: 6e 63 72 20 69 5d 5d 20 7d 0a 20 20 20 20 20 20  ncr i]] }.      
12f0: 2d 75 73 69 6e 67 20 20 7b 20 73 65 74 20 75 73  -using  { set us
1300: 69 6e 67 6c 69 73 74 20 5b 6c 69 6e 64 65 78 20  inglist [lindex 
1310: 24 61 72 67 73 20 5b 69 6e 63 72 20 69 5d 5d 20  $args [incr i]] 
1320: 7d 0a 20 20 20 20 20 20 2d 6c 65 66 74 20 20 20  }.      -left   
1330: 7b 20 73 65 74 20 69 73 6c 65 66 74 20 31 20 7d  { set isleft 1 }
1340: 0a 20 20 20 20 20 20 64 65 66 61 75 6c 74 20 7b  .      default {
1350: 0a 20 20 20 20 20 20 20 20 65 72 72 6f 72 20 22  .        error "
1360: 55 6e 6b 6e 6f 77 6e 20 61 72 67 75 6d 65 6e 74  Unknown argument
1370: 3a 20 24 61 22 0a 20 20 20 20 20 20 7d 0a 20 20  : $a".      }.  
1380: 20 20 7d 0a 20 20 7d 0a 0a 20 20 73 65 74 20 63    }.  }..  set c
1390: 31 20 5b 6c 69 6e 64 65 78 20 24 64 61 74 61 31  1 [lindex $data1
13a0: 20 30 5d 0a 20 20 73 65 74 20 63 32 20 5b 6c 69   0].  set c2 [li
13b0: 6e 64 65 78 20 24 64 61 74 61 32 20 30 5d 0a 20  ndex $data2 0]. 
13c0: 20 73 65 74 20 6f 6d 69 74 6c 69 73 74 20 5b 6c   set omitlist [l
13d0: 69 73 74 5d 0a 20 20 73 65 74 20 6e 75 6c 6c 72  ist].  set nullr
13e0: 6f 77 6c 69 73 74 20 5b 6c 69 73 74 5d 0a 20 20  owlist [list].  
13f0: 73 65 74 20 63 72 65 74 20 24 63 31 0a 0a 20 20  set cret $c1..  
1400: 73 65 74 20 63 69 64 78 20 30 0a 20 20 66 6f 72  set cidx 0.  for
1410: 65 61 63 68 20 63 6f 6c 20 24 63 32 20 7b 0a 20  each col $c2 {. 
1420: 20 20 20 73 65 74 20 69 64 78 20 5b 6c 73 65 61     set idx [lsea
1430: 72 63 68 20 24 75 73 69 6e 67 6c 69 73 74 20 24  rch $usinglist $
1440: 63 6f 6c 5d 0a 20 20 20 20 69 66 20 7b 24 69 64  col].    if {$id
1450: 78 3e 3d 30 7d 20 7b 6c 61 70 70 65 6e 64 20 6f  x>=0} {lappend o
1460: 6d 69 74 6c 69 73 74 20 24 63 69 64 78 7d 0a 20  mitlist $cidx}. 
1470: 20 20 20 69 66 20 7b 24 69 64 78 3c 30 7d 20 7b     if {$idx<0} {
1480: 0a 20 20 20 20 20 20 6c 61 70 70 65 6e 64 20 6e  .      lappend n
1490: 75 6c 6c 72 6f 77 6c 69 73 74 20 7b 4e 55 4c 4c  ullrowlist {NULL
14a0: 20 7b 7d 7d 0a 20 20 20 20 20 20 6c 61 70 70 65   {}}.      lappe
14b0: 6e 64 20 63 72 65 74 20 24 63 6f 6c 0a 20 20 20  nd cret $col.   
14c0: 20 7d 0a 20 20 20 20 69 6e 63 72 20 63 69 64 78   }.    incr cidx
14d0: 0a 20 20 7d 0a 20 20 73 65 74 20 6f 6d 69 74 6c  .  }.  set omitl
14e0: 69 73 74 20 5b 6c 73 6f 72 74 20 2d 69 6e 74 65  ist [lsort -inte
14f0: 67 65 72 20 2d 64 65 63 72 65 61 73 69 6e 67 20  ger -decreasing 
1500: 24 6f 6d 69 74 6c 69 73 74 5d 0a 0a 0a 20 20 73  $omitlist]...  s
1510: 65 74 20 72 72 65 74 20 5b 6c 69 73 74 5d 0a 20  et rret [list]. 
1520: 20 66 6f 72 65 61 63 68 20 72 31 20 5b 6c 69 6e   foreach r1 [lin
1530: 64 65 78 20 24 64 61 74 61 31 20 31 5d 20 7b 0a  dex $data1 1] {.
1540: 20 20 20 20 73 65 74 20 6f 6e 65 20 30 0a 20 20      set one 0.  
1550: 20 20 66 6f 72 65 61 63 68 20 72 32 20 5b 6c 69    foreach r2 [li
1560: 6e 64 65 78 20 24 64 61 74 61 32 20 31 5d 20 7b  ndex $data2 1] {
1570: 0a 20 20 20 20 20 20 73 65 74 20 6f 6b 20 31 0a  .      set ok 1.
1580: 20 20 20 20 20 20 69 66 20 7b 24 74 65 73 74 70        if {$testp
1590: 72 6f 63 20 21 3d 20 22 22 7d 20 7b 0a 20 20 20  roc != ""} {.   
15a0: 20 20 20 20 20 73 65 74 20 6f 6b 20 5b 65 76 61       set ok [eva
15b0: 6c 20 24 74 65 73 74 70 72 6f 63 20 5b 6c 69 73  l $testproc [lis
15c0: 74 20 24 63 31 20 24 72 31 20 24 63 32 20 24 72  t $c1 $r1 $c2 $r
15d0: 32 5d 5d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  2]].      }.    
15e0: 20 20 69 66 20 7b 24 6f 6b 7d 20 7b 0a 20 20 20    if {$ok} {.   
15f0: 20 20 20 20 20 73 65 74 20 6f 6e 65 20 31 0a 20       set one 1. 
1600: 20 20 20 20 20 20 20 66 6f 72 65 61 63 68 20 69         foreach i
1610: 64 78 20 24 6f 6d 69 74 6c 69 73 74 20 7b 73 65  dx $omitlist {se
1620: 74 20 72 32 20 5b 6c 72 65 70 6c 61 63 65 20 24  t r2 [lreplace $
1630: 72 32 20 24 69 64 78 20 24 69 64 78 5d 7d 0a 20  r2 $idx $idx]}. 
1640: 20 20 20 20 20 20 20 6c 61 70 70 65 6e 64 20 72         lappend r
1650: 72 65 74 20 5b 63 6f 6e 63 61 74 20 24 72 31 20  ret [concat $r1 
1660: 24 72 32 5d 0a 20 20 20 20 20 20 7d 0a 20 20 20  $r2].      }.   
1670: 20 7d 0a 0a 20 20 20 20 69 66 20 7b 24 69 73 6c   }..    if {$isl
1680: 65 66 74 20 26 26 20 24 6f 6e 65 3d 3d 30 7d 20  eft && $one==0} 
1690: 7b 0a 20 20 20 20 20 20 6c 61 70 70 65 6e 64 20  {.      lappend 
16a0: 72 72 65 74 20 5b 63 6f 6e 63 61 74 20 24 72 31  rret [concat $r1
16b0: 20 24 6e 75 6c 6c 72 6f 77 6c 69 73 74 5d 0a 20   $nullrowlist]. 
16c0: 20 20 20 7d 0a 20 20 7d 0a 20 20 0a 20 20 6c 69     }.  }.  .  li
16d0: 73 74 20 24 63 72 65 74 20 24 72 72 65 74 0a 7d  st $cret $rret.}
16e0: 0a 0a 70 72 6f 63 20 74 65 5f 74 62 6c 6a 6f 69  ..proc te_tbljoi
16f0: 6e 20 7b 64 62 20 74 31 20 74 32 20 61 72 67 73  n {db t1 t2 args
1700: 7d 20 7b 0a 20 20 74 65 5f 6a 6f 69 6e 20 5b 74  } {.  te_join [t
1710: 65 5f 72 65 61 64 5f 74 62 6c 20 24 64 62 20 24  e_read_tbl $db $
1720: 74 31 5d 20 5b 74 65 5f 72 65 61 64 5f 74 62 6c  t1] [te_read_tbl
1730: 20 24 64 62 20 24 74 32 5d 20 7b 2a 7d 24 61 72   $db $t2] {*}$ar
1740: 67 73 0a 7d 0a 0a 70 72 6f 63 20 74 65 5f 61 70  gs.}..proc te_ap
1750: 70 6c 79 5f 61 66 66 69 6e 69 74 79 20 7b 61 66  ply_affinity {af
1760: 66 69 6e 69 74 79 20 74 79 70 65 76 61 72 20 76  finity typevar v
1770: 61 6c 76 61 72 7d 20 7b 0a 20 20 75 70 76 61 72  alvar} {.  upvar
1780: 20 24 74 79 70 65 76 61 72 20 74 79 70 65 0a 20   $typevar type. 
1790: 20 75 70 76 61 72 20 24 76 61 6c 76 61 72 20 76   upvar $valvar v
17a0: 61 6c 0a 0a 20 20 73 77 69 74 63 68 20 2d 2d 20  al..  switch -- 
17b0: 24 61 66 66 69 6e 69 74 79 20 7b 0a 20 20 20 20  $affinity {.    
17c0: 69 6e 74 65 67 65 72 20 7b 0a 20 20 20 20 20 20  integer {.      
17d0: 69 66 20 7b 5b 73 74 72 69 6e 67 20 69 73 20 64  if {[string is d
17e0: 6f 75 62 6c 65 20 24 76 61 6c 5d 7d 20 7b 20 73  ouble $val]} { s
17f0: 65 74 20 74 79 70 65 20 52 45 41 4c 20 7d 0a 20  et type REAL }. 
1800: 20 20 20 20 20 69 66 20 7b 5b 73 74 72 69 6e 67       if {[string
1810: 20 69 73 20 77 69 64 65 69 6e 74 65 67 65 72 20   is wideinteger 
1820: 24 76 61 6c 5d 7d 20 7b 20 73 65 74 20 74 79 70  $val]} { set typ
1830: 65 20 49 4e 54 45 47 45 52 20 7d 0a 20 20 20 20  e INTEGER }.    
1840: 20 20 69 66 20 7b 24 74 79 70 65 20 3d 3d 20 22    if {$type == "
1850: 52 45 41 4c 22 20 26 26 20 69 6e 74 28 24 76 61  REAL" && int($va
1860: 6c 29 3d 3d 24 76 61 6c 7d 20 7b 20 0a 20 20 20  l)==$val} { .   
1870: 20 20 20 20 20 73 65 74 20 74 79 70 65 20 49 4e       set type IN
1880: 54 45 47 45 52 20 0a 20 20 20 20 20 20 20 20 73  TEGER .        s
1890: 65 74 20 76 61 6c 20 5b 65 78 70 72 20 7b 69 6e  et val [expr {in
18a0: 74 28 24 76 61 6c 29 7d 5d 0a 20 20 20 20 20 20  t($val)}].      
18b0: 7d 0a 20 20 20 20 7d 0a 20 20 20 20 74 65 78 74  }.    }.    text
18c0: 20 7b 0a 20 20 20 20 20 20 73 65 74 20 74 79 70   {.      set typ
18d0: 65 20 54 45 58 54 0a 20 20 20 20 7d 0a 20 20 20  e TEXT.    }.   
18e0: 20 6e 6f 6e 65 20 7b 20 7d 0a 0a 20 20 20 20 64   none { }..    d
18f0: 65 66 61 75 6c 74 20 7b 20 65 72 72 6f 72 20 22  efault { error "
1900: 69 6e 76 61 6c 69 64 20 61 66 66 69 6e 69 74 79  invalid affinity
1910: 3a 20 24 61 66 66 69 6e 69 74 79 22 20 7d 0a 20  : $affinity" }. 
1920: 20 7d 0a 7d 0a 0a 23 2d 2d 2d 2d 2d 2d 2d 2d 2d   }.}..#---------
1930: 2d 0a 23 20 74 65 5f 65 71 75 61 6c 73 20 3f 53  -.# te_equals ?S
1940: 57 49 54 43 48 45 53 3f 20 63 31 20 63 32 20 63  WITCHES? c1 c2 c
1950: 6f 6c 73 31 20 72 6f 77 31 20 63 6f 6c 73 32 20  ols1 row1 cols2 
1960: 72 6f 77 32 0a 23 0a 70 72 6f 63 20 74 65 5f 65  row2.#.proc te_e
1970: 71 75 61 6c 73 20 7b 61 72 67 73 7d 20 7b 0a 0a  quals {args} {..
1980: 20 20 69 66 20 7b 5b 6c 6c 65 6e 67 74 68 20 24    if {[llength $
1990: 61 72 67 73 5d 3c 36 7d 20 7b 65 72 72 6f 72 20  args]<6} {error 
19a0: 22 69 6e 76 61 6c 69 64 20 61 72 67 75 6d 65 6e  "invalid argumen
19b0: 74 73 20 74 6f 20 74 65 5f 65 71 75 61 6c 73 22  ts to te_equals"
19c0: 7d 0a 20 20 66 6f 72 65 61 63 68 20 7b 63 31 20  }.  foreach {c1 
19d0: 63 32 20 63 6f 6c 73 31 20 72 6f 77 31 20 63 6f  c2 cols1 row1 co
19e0: 6c 73 32 20 72 6f 77 32 7d 20 5b 6c 72 61 6e 67  ls2 row2} [lrang
19f0: 65 20 24 61 72 67 73 20 65 6e 64 2d 35 20 65 6e  e $args end-5 en
1a00: 64 5d 20 62 72 65 61 6b 0a 0a 20 20 73 65 74 20  d] break..  set 
1a10: 6e 6f 63 61 73 65 20 30 0a 20 20 73 65 74 20 61  nocase 0.  set a
1a20: 66 66 69 6e 69 74 79 20 6e 6f 6e 65 0a 0a 20 20  ffinity none..  
1a30: 66 6f 72 20 7b 73 65 74 20 69 20 30 7d 20 7b 24  for {set i 0} {$
1a40: 69 20 3c 20 28 5b 6c 6c 65 6e 67 74 68 20 24 61  i < ([llength $a
1a50: 72 67 73 5d 2d 36 29 7d 20 7b 69 6e 63 72 20 69  rgs]-6)} {incr i
1a60: 7d 20 7b 0a 20 20 20 20 73 65 74 20 61 20 5b 6c  } {.    set a [l
1a70: 69 6e 64 65 78 20 24 61 72 67 73 20 24 69 5d 0a  index $args $i].
1a80: 20 20 20 20 73 77 69 74 63 68 20 2d 2d 20 24 61      switch -- $a
1a90: 20 7b 0a 20 20 20 20 20 20 2d 6e 6f 63 61 73 65   {.      -nocase
1aa0: 20 7b 0a 20 20 20 20 20 20 20 20 73 65 74 20 6e   {.        set n
1ab0: 6f 63 61 73 65 20 31 0a 20 20 20 20 20 20 7d 0a  ocase 1.      }.
1ac0: 20 20 20 20 20 20 2d 61 66 66 69 6e 69 74 79 20        -affinity 
1ad0: 7b 0a 20 20 20 20 20 20 20 20 73 65 74 20 61 66  {.        set af
1ae0: 66 69 6e 69 74 79 20 5b 73 74 72 69 6e 67 20 74  finity [string t
1af0: 6f 6c 6f 77 65 72 20 5b 6c 69 6e 64 65 78 20 24  olower [lindex $
1b00: 61 72 67 73 20 5b 69 6e 63 72 20 69 5d 5d 5d 0a  args [incr i]]].
1b10: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 64 65        }.      de
1b20: 66 61 75 6c 74 20 7b 0a 20 20 20 20 20 20 20 20  fault {.        
1b30: 65 72 72 6f 72 20 22 69 6e 76 61 6c 69 64 20 61  error "invalid a
1b40: 72 67 75 6d 65 6e 74 73 20 74 6f 20 74 65 5f 65  rguments to te_e
1b50: 71 75 61 6c 73 22 0a 20 20 20 20 20 20 7d 0a 20  quals".      }. 
1b60: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 73 65 74 20     }.  }..  set 
1b70: 69 64 78 32 20 5b 69 66 20 7b 5b 73 74 72 69 6e  idx2 [if {[strin
1b80: 67 20 69 73 20 69 6e 74 65 67 65 72 20 24 63 32  g is integer $c2
1b90: 5d 7d 20 7b 20 73 65 74 20 63 32 20 7d 20 65 6c  ]} { set c2 } el
1ba0: 73 65 20 7b 20 6c 73 65 61 72 63 68 20 24 63 6f  se { lsearch $co
1bb0: 6c 73 32 20 24 63 32 20 7d 5d 0a 20 20 73 65 74  ls2 $c2 }].  set
1bc0: 20 69 64 78 31 20 5b 69 66 20 7b 5b 73 74 72 69   idx1 [if {[stri
1bd0: 6e 67 20 69 73 20 69 6e 74 65 67 65 72 20 24 63  ng is integer $c
1be0: 31 5d 7d 20 7b 20 73 65 74 20 63 31 20 7d 20 65  1]} { set c1 } e
1bf0: 6c 73 65 20 7b 20 6c 73 65 61 72 63 68 20 24 63  lse { lsearch $c
1c00: 6f 6c 73 31 20 24 63 31 20 7d 5d 0a 0a 20 20 73  ols1 $c1 }]..  s
1c10: 65 74 20 74 31 20 5b 6c 69 6e 64 65 78 20 24 72  et t1 [lindex $r
1c20: 6f 77 31 20 24 69 64 78 31 20 30 5d 0a 20 20 73  ow1 $idx1 0].  s
1c30: 65 74 20 74 32 20 5b 6c 69 6e 64 65 78 20 24 72  et t2 [lindex $r
1c40: 6f 77 32 20 24 69 64 78 32 20 30 5d 0a 20 20 73  ow2 $idx2 0].  s
1c50: 65 74 20 76 31 20 5b 6c 69 6e 64 65 78 20 24 72  et v1 [lindex $r
1c60: 6f 77 31 20 24 69 64 78 31 20 31 5d 0a 20 20 73  ow1 $idx1 1].  s
1c70: 65 74 20 76 32 20 5b 6c 69 6e 64 65 78 20 24 72  et v2 [lindex $r
1c80: 6f 77 32 20 24 69 64 78 32 20 31 5d 0a 0a 20 20  ow2 $idx2 1]..  
1c90: 74 65 5f 61 70 70 6c 79 5f 61 66 66 69 6e 69 74  te_apply_affinit
1ca0: 79 20 24 61 66 66 69 6e 69 74 79 20 74 31 20 76  y $affinity t1 v
1cb0: 31 0a 20 20 74 65 5f 61 70 70 6c 79 5f 61 66 66  1.  te_apply_aff
1cc0: 69 6e 69 74 79 20 24 61 66 66 69 6e 69 74 79 20  inity $affinity 
1cd0: 74 32 20 76 32 0a 0a 20 20 69 66 20 7b 24 74 31  t2 v2..  if {$t1
1ce0: 20 3d 3d 20 22 4e 55 4c 4c 22 20 7c 7c 20 24 74   == "NULL" || $t
1cf0: 32 20 3d 3d 20 22 4e 55 4c 4c 22 7d 20 7b 20 72  2 == "NULL"} { r
1d00: 65 74 75 72 6e 20 30 20 7d 0a 20 20 69 66 20 7b  eturn 0 }.  if {
1d10: 24 6e 6f 63 61 73 65 20 26 26 20 24 74 31 20 3d  $nocase && $t1 =
1d20: 3d 20 22 54 45 58 54 22 7d 20 7b 20 73 65 74 20  = "TEXT"} { set 
1d30: 76 31 20 5b 73 74 72 69 6e 67 20 74 6f 6c 6f 77  v1 [string tolow
1d40: 65 72 20 24 76 31 5d 20 7d 0a 20 20 69 66 20 7b  er $v1] }.  if {
1d50: 24 6e 6f 63 61 73 65 20 26 26 20 24 74 32 20 3d  $nocase && $t2 =
1d60: 3d 20 22 54 45 58 54 22 7d 20 7b 20 73 65 74 20  = "TEXT"} { set 
1d70: 76 32 20 5b 73 74 72 69 6e 67 20 74 6f 6c 6f 77  v2 [string tolow
1d80: 65 72 20 24 76 32 5d 20 7d 0a 0a 0a 20 20 73 65  er $v2] }...  se
1d90: 74 20 72 65 73 20 5b 65 78 70 72 20 7b 24 74 31  t res [expr {$t1
1da0: 20 3d 3d 20 24 74 32 20 26 26 20 5b 73 74 72 69   == $t2 && [stri
1db0: 6e 67 20 65 71 75 61 6c 20 24 76 31 20 24 76 32  ng equal $v1 $v2
1dc0: 5d 7d 5d 0a 20 20 72 65 74 75 72 6e 20 24 72 65  ]}].  return $re
1dd0: 73 0a 7d 0a 0a 70 72 6f 63 20 74 65 5f 66 61 6c  s.}..proc te_fal
1de0: 73 65 20 7b 61 72 67 73 7d 20 7b 20 72 65 74 75  se {args} { retu
1df0: 72 6e 20 30 20 7d 0a 70 72 6f 63 20 74 65 5f 74  rn 0 }.proc te_t
1e00: 72 75 65 20 20 7b 61 72 67 73 7d 20 7b 20 72 65  rue  {args} { re
1e10: 74 75 72 6e 20 31 20 7d 0a 0a 70 72 6f 63 20 74  turn 1 }..proc t
1e20: 65 5f 61 6e 64 20 7b 61 72 67 73 7d 20 7b 0a 20  e_and {args} {. 
1e30: 20 66 6f 72 65 61 63 68 20 61 20 5b 6c 72 61 6e   foreach a [lran
1e40: 67 65 20 24 61 72 67 73 20 30 20 65 6e 64 2d 34  ge $args 0 end-4
1e50: 5d 20 7b 0a 20 20 20 20 73 65 74 20 72 65 73 20  ] {.    set res 
1e60: 5b 65 76 61 6c 20 24 61 20 5b 6c 72 61 6e 67 65  [eval $a [lrange
1e70: 20 24 61 72 67 73 20 65 6e 64 2d 33 20 65 6e 64   $args end-3 end
1e80: 5d 5d 0a 20 20 20 20 69 66 20 7b 24 72 65 73 20  ]].    if {$res 
1e90: 3d 3d 20 30 7d 20 7b 72 65 74 75 72 6e 20 30 7d  == 0} {return 0}
1ea0: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 31 0a  .  }.  return 1.
1eb0: 7d 0a 0a 0a 70 72 6f 63 20 74 65 5f 64 61 74 61  }...proc te_data
1ec0: 73 65 74 5f 65 71 20 7b 74 65 73 74 6e 61 6d 65  set_eq {testname
1ed0: 20 67 6f 74 20 65 78 70 65 63 74 65 64 7d 20 7b   got expected} {
1ee0: 0a 20 20 75 70 6c 65 76 65 6c 20 23 30 20 5b 6c  .  uplevel #0 [l
1ef0: 69 73 74 20 64 6f 5f 74 65 73 74 20 24 74 65 73  ist do_test $tes
1f00: 74 6e 61 6d 65 20 5b 6c 69 73 74 20 73 65 74 20  tname [list set 
1f10: 7b 7d 20 24 67 6f 74 5d 20 24 65 78 70 65 63 74  {} $got] $expect
1f20: 65 64 5d 0a 7d 0a 70 72 6f 63 20 74 65 5f 64 61  ed].}.proc te_da
1f30: 74 61 73 65 74 5f 65 71 5f 75 6e 6f 72 64 65 72  taset_eq_unorder
1f40: 65 64 20 7b 74 65 73 74 6e 61 6d 65 20 67 6f 74  ed {testname got
1f50: 20 65 78 70 65 63 74 65 64 7d 20 7b 0a 20 20 6c   expected} {.  l
1f60: 73 65 74 20 67 6f 74 20 20 20 20 20 20 31 20 5b  set got      1 [
1f70: 6c 73 6f 72 74 20 5b 6c 69 6e 64 65 78 20 24 67  lsort [lindex $g
1f80: 6f 74 20 31 5d 5d 0a 20 20 6c 73 65 74 20 65 78  ot 1]].  lset ex
1f90: 70 65 63 74 65 64 20 31 20 5b 6c 73 6f 72 74 20  pected 1 [lsort 
1fa0: 5b 6c 69 6e 64 65 78 20 24 65 78 70 65 63 74 65  [lindex $expecte
1fb0: 64 20 31 5d 5d 0a 20 20 74 65 5f 64 61 74 61 73  d 1]].  te_datas
1fc0: 65 74 5f 65 71 20 24 74 65 73 74 6e 61 6d 65 20  et_eq $testname 
1fd0: 24 67 6f 74 20 24 65 78 70 65 63 74 65 64 0a 7d  $got $expected.}
1fe0: 0a 0a 70 72 6f 63 20 74 65 5f 64 61 74 61 73 65  ..proc te_datase
1ff0: 74 5f 6e 65 20 7b 74 65 73 74 6e 61 6d 65 20 67  t_ne {testname g
2000: 6f 74 20 75 6e 65 78 70 65 63 74 65 64 7d 20 7b  ot unexpected} {
2010: 0a 20 20 75 70 6c 65 76 65 6c 20 23 30 20 5b 6c  .  uplevel #0 [l
2020: 69 73 74 20 64 6f 5f 74 65 73 74 20 24 74 65 73  ist do_test $tes
2030: 74 6e 61 6d 65 20 5b 6c 69 73 74 20 73 74 72 69  tname [list stri
2040: 6e 67 20 65 71 75 61 6c 20 24 67 6f 74 20 24 75  ng equal $got $u
2050: 6e 65 78 70 65 63 74 65 64 5d 20 30 5d 0a 7d 0a  nexpected] 0].}.
2060: 70 72 6f 63 20 74 65 5f 64 61 74 61 73 65 74 5f  proc te_dataset_
2070: 6e 65 5f 75 6e 6f 72 64 65 72 65 64 20 7b 74 65  ne_unordered {te
2080: 73 74 6e 61 6d 65 20 67 6f 74 20 75 6e 65 78 70  stname got unexp
2090: 65 63 74 65 64 7d 20 7b 0a 20 20 6c 73 65 74 20  ected} {.  lset 
20a0: 67 6f 74 20 20 20 20 20 20 31 20 5b 6c 73 6f 72  got      1 [lsor
20b0: 74 20 5b 6c 69 6e 64 65 78 20 24 67 6f 74 20 31  t [lindex $got 1
20c0: 5d 5d 0a 20 20 6c 73 65 74 20 75 6e 65 78 70 65  ]].  lset unexpe
20d0: 63 74 65 64 20 31 20 5b 6c 73 6f 72 74 20 5b 6c  cted 1 [lsort [l
20e0: 69 6e 64 65 78 20 24 75 6e 65 78 70 65 63 74 65  index $unexpecte
20f0: 64 20 31 5d 5d 0a 20 20 74 65 5f 64 61 74 61 73  d 1]].  te_datas
2100: 65 74 5f 6e 65 20 24 74 65 73 74 6e 61 6d 65 20  et_ne $testname 
2110: 24 67 6f 74 20 24 75 6e 65 78 70 65 63 74 65 64  $got $unexpected
2120: 0a 7d 0a 0a 0a 23 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  .}...#----------
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 0a  ---------------.
2170: 23 0a 70 72 6f 63 20 74 65 73 74 5f 6a 6f 69 6e  #.proc test_join
2180: 20 7b 74 6e 20 73 71 6c 6a 6f 69 6e 20 74 62 6c   {tn sqljoin tbl
2190: 6a 6f 69 6e 61 72 67 73 7d 20 7b 0a 20 20 73 65  joinargs} {.  se
21a0: 74 20 73 71 6c 20 5b 74 65 5f 72 65 61 64 5f 73  t sql [te_read_s
21b0: 71 6c 20 64 62 20 22 53 45 4c 45 43 54 20 2a 20  ql db "SELECT * 
21c0: 46 52 4f 4d 20 24 73 71 6c 6a 6f 69 6e 22 5d 0a  FROM $sqljoin"].
21d0: 20 20 73 65 74 20 74 65 20 20 5b 74 65 5f 74 62    set te  [te_tb
21e0: 6c 6a 6f 69 6e 20 64 62 20 7b 2a 7d 24 74 62 6c  ljoin db {*}$tbl
21f0: 6a 6f 69 6e 61 72 67 73 5d 0a 20 20 74 65 5f 64  joinargs].  te_d
2200: 61 74 61 73 65 74 5f 65 71 5f 75 6e 6f 72 64 65  ataset_eq_unorde
2210: 72 65 64 20 24 74 6e 20 24 73 71 6c 20 24 74 65  red $tn $sql $te
2220: 0a 7d 0a 0a 64 72 6f 70 5f 61 6c 6c 5f 74 61 62  .}..drop_all_tab
2230: 6c 65 73 0a 64 6f 5f 65 78 65 63 73 71 6c 5f 74  les.do_execsql_t
2240: 65 73 74 20 65 5f 73 65 6c 65 63 74 32 2d 30 20  est e_select2-0 
2250: 7b 0a 20 20 43 52 45 41 54 45 20 54 41 42 4c 45  {.  CREATE TABLE
2260: 20 74 31 28 61 2c 20 62 29 3b 0a 20 20 43 52 45   t1(a, b);.  CRE
2270: 41 54 45 20 54 41 42 4c 45 20 74 32 28 61 2c 20  ATE TABLE t2(a, 
2280: 62 29 3b 0a 20 20 43 52 45 41 54 45 20 54 41 42  b);.  CREATE TAB
2290: 4c 45 20 74 33 28 62 20 43 4f 4c 4c 41 54 45 20  LE t3(b COLLATE 
22a0: 6e 6f 63 61 73 65 29 3b 0a 0a 20 20 49 4e 53 45  nocase);..  INSE
22b0: 52 54 20 49 4e 54 4f 20 74 31 20 56 41 4c 55 45  RT INTO t1 VALUE
22c0: 53 28 32 2c 20 27 42 27 29 3b 0a 20 20 49 4e 53  S(2, 'B');.  INS
22d0: 45 52 54 20 49 4e 54 4f 20 74 31 20 56 41 4c 55  ERT INTO t1 VALU
22e0: 45 53 28 31 2c 20 27 41 27 29 3b 0a 20 20 49 4e  ES(1, 'A');.  IN
22f0: 53 45 52 54 20 49 4e 54 4f 20 74 31 20 56 41 4c  SERT INTO t1 VAL
2300: 55 45 53 28 34 2c 20 27 44 27 29 3b 0a 20 20 49  UES(4, 'D');.  I
2310: 4e 53 45 52 54 20 49 4e 54 4f 20 74 31 20 56 41  NSERT INTO t1 VA
2320: 4c 55 45 53 28 4e 55 4c 4c 2c 20 4e 55 4c 4c 29  LUES(NULL, NULL)
2330: 3b 0a 20 20 49 4e 53 45 52 54 20 49 4e 54 4f 20  ;.  INSERT INTO 
2340: 74 31 20 56 41 4c 55 45 53 28 33 2c 20 4e 55 4c  t1 VALUES(3, NUL
2350: 4c 29 3b 0a 0a 20 20 49 4e 53 45 52 54 20 49 4e  L);..  INSERT IN
2360: 54 4f 20 74 32 20 56 41 4c 55 45 53 28 31 2c 20  TO t2 VALUES(1, 
2370: 27 41 27 29 3b 0a 20 20 49 4e 53 45 52 54 20 49  'A');.  INSERT I
2380: 4e 54 4f 20 74 32 20 56 41 4c 55 45 53 28 32 2c  NTO t2 VALUES(2,
2390: 20 4e 55 4c 4c 29 3b 0a 20 20 49 4e 53 45 52 54   NULL);.  INSERT
23a0: 20 49 4e 54 4f 20 74 32 20 56 41 4c 55 45 53 28   INTO t2 VALUES(
23b0: 35 2c 20 27 45 27 29 3b 0a 20 20 49 4e 53 45 52  5, 'E');.  INSER
23c0: 54 20 49 4e 54 4f 20 74 32 20 56 41 4c 55 45 53  T INTO t2 VALUES
23d0: 28 4e 55 4c 4c 2c 20 4e 55 4c 4c 29 3b 0a 20 20  (NULL, NULL);.  
23e0: 49 4e 53 45 52 54 20 49 4e 54 4f 20 74 32 20 56  INSERT INTO t2 V
23f0: 41 4c 55 45 53 28 33 2c 20 27 43 27 29 3b 0a 0a  ALUES(3, 'C');..
2400: 20 20 49 4e 53 45 52 54 20 49 4e 54 4f 20 74 33    INSERT INTO t3
2410: 20 56 41 4c 55 45 53 28 27 61 27 29 3b 0a 20 20   VALUES('a');.  
2420: 49 4e 53 45 52 54 20 49 4e 54 4f 20 74 33 20 56  INSERT INTO t3 V
2430: 41 4c 55 45 53 28 27 63 27 29 3b 0a 20 20 49 4e  ALUES('c');.  IN
2440: 53 45 52 54 20 49 4e 54 4f 20 74 33 20 56 41 4c  SERT INTO t3 VAL
2450: 55 45 53 28 27 62 27 29 3b 0a 7d 20 7b 7d 0a 0a  UES('b');.} {}..
2460: 66 6f 72 65 61 63 68 20 7b 74 6e 20 69 6e 64 65  foreach {tn inde
2470: 78 65 73 7d 20 7b 0a 20 20 65 5f 73 65 6c 65 63  xes} {.  e_selec
2480: 74 32 2d 31 2e 31 20 7b 20 7d 0a 20 20 65 5f 73  t2-1.1 { }.  e_s
2490: 65 6c 65 63 74 32 2d 31 2e 32 20 7b 20 43 52 45  elect2-1.2 { CRE
24a0: 41 54 45 20 49 4e 44 45 58 20 69 31 20 4f 4e 20  ATE INDEX i1 ON 
24b0: 74 31 28 61 29 20 7d 0a 20 20 65 5f 73 65 6c 65  t1(a) }.  e_sele
24c0: 63 74 32 2d 31 2e 33 20 7b 20 43 52 45 41 54 45  ct2-1.3 { CREATE
24d0: 20 49 4e 44 45 58 20 69 31 20 4f 4e 20 74 32 28   INDEX i1 ON t2(
24e0: 61 29 20 7d 0a 20 20 65 5f 73 65 6c 65 63 74 32  a) }.  e_select2
24f0: 2d 31 2e 34 20 7b 20 43 52 45 41 54 45 20 49 4e  -1.4 { CREATE IN
2500: 44 45 58 20 69 31 20 4f 4e 20 74 33 28 62 29 20  DEX i1 ON t3(b) 
2510: 7d 0a 7d 20 7b 0a 0a 20 20 63 61 74 63 68 73 71  }.} {..  catchsq
2520: 6c 20 7b 20 44 52 4f 50 20 49 4e 44 45 58 20 69  l { DROP INDEX i
2530: 31 20 7d 0a 20 20 63 61 74 63 68 73 71 6c 20 7b  1 }.  catchsql {
2540: 20 44 52 4f 50 20 49 4e 44 45 58 20 69 32 20 7d   DROP INDEX i2 }
2550: 0a 20 20 63 61 74 63 68 73 71 6c 20 7b 20 44 52  .  catchsql { DR
2560: 4f 50 20 49 4e 44 45 58 20 69 33 20 7d 0a 20 20  OP INDEX i3 }.  
2570: 65 78 65 63 73 71 6c 20 24 69 6e 64 65 78 65 73  execsql $indexes
2580: 0a 0a 20 20 23 20 45 56 49 44 45 4e 43 45 2d 4f  ..  # EVIDENCE-O
2590: 46 3a 20 52 2d 34 36 31 32 32 2d 31 34 39 33 30  F: R-46122-14930
25a0: 20 49 66 20 74 68 65 20 6a 6f 69 6e 2d 6f 70 20   If the join-op 
25b0: 69 73 20 22 43 52 4f 53 53 20 4a 4f 49 4e 22 2c  is "CROSS JOIN",
25c0: 20 22 49 4e 4e 45 52 0a 20 20 23 20 4a 4f 49 4e   "INNER.  # JOIN
25d0: 22 2c 20 22 4a 4f 49 4e 22 20 6f 72 20 61 20 63  ", "JOIN" or a c
25e0: 6f 6d 6d 61 20 28 22 2c 22 29 20 61 6e 64 20 74  omma (",") and t
25f0: 68 65 72 65 20 69 73 20 6e 6f 20 4f 4e 20 6f 72  here is no ON or
2600: 20 55 53 49 4e 47 20 63 6c 61 75 73 65 2c 0a 20   USING clause,. 
2610: 20 23 20 74 68 65 6e 20 74 68 65 20 72 65 73 75   # then the resu
2620: 6c 74 20 6f 66 20 74 68 65 20 6a 6f 69 6e 20 69  lt of the join i
2630: 73 20 73 69 6d 70 6c 79 20 74 68 65 20 63 61 72  s simply the car
2640: 74 65 73 69 61 6e 20 70 72 6f 64 75 63 74 20 6f  tesian product o
2650: 66 20 74 68 65 0a 20 20 23 20 6c 65 66 74 20 61  f the.  # left a
2660: 6e 64 20 72 69 67 68 74 2d 68 61 6e 64 20 64 61  nd right-hand da
2670: 74 61 73 65 74 73 2e 0a 20 20 23 0a 20 20 23 20  tasets..  #.  # 
2680: 45 56 49 44 45 4e 43 45 2d 4f 46 3a 20 52 2d 34  EVIDENCE-OF: R-4
2690: 36 32 35 36 2d 35 37 32 34 33 20 54 68 65 72 65  6256-57243 There
26a0: 20 69 73 20 6e 6f 20 64 69 66 66 65 72 65 6e 63   is no differenc
26b0: 65 20 62 65 74 77 65 65 6e 20 74 68 65 20 22 49  e between the "I
26c0: 4e 4e 45 52 0a 20 20 23 20 4a 4f 49 4e 22 2c 20  NNER.  # JOIN", 
26d0: 22 4a 4f 49 4e 22 20 61 6e 64 20 22 2c 22 20 6a  "JOIN" and "," j
26e0: 6f 69 6e 20 6f 70 65 72 61 74 6f 72 73 2e 0a 20  oin operators.. 
26f0: 20 23 0a 20 20 23 20 45 56 49 44 45 4e 43 45 2d   #.  # EVIDENCE-
2700: 4f 46 3a 20 52 2d 30 37 35 34 34 2d 32 34 31 35  OF: R-07544-2415
2710: 35 20 54 68 65 20 22 43 52 4f 53 53 20 4a 4f 49  5 The "CROSS JOI
2720: 4e 22 20 6a 6f 69 6e 20 6f 70 65 72 61 74 6f 72  N" join operator
2730: 20 70 72 6f 64 75 63 65 73 20 74 68 65 0a 20 20   produces the.  
2740: 23 20 73 61 6d 65 20 64 61 74 61 20 61 73 20 74  # same data as t
2750: 68 65 20 22 49 4e 4e 45 52 20 4a 4f 49 4e 22 2c  he "INNER JOIN",
2760: 20 22 4a 4f 49 4e 22 20 61 6e 64 20 22 2c 22 20   "JOIN" and "," 
2770: 6f 70 65 72 61 74 6f 72 73 0a 20 20 23 0a 20 20  operators.  #.  
2780: 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e  test_join $tn.1.
2790: 31 20 20 22 74 31 2c 20 74 32 22 20 20 20 20 20  1  "t1, t2"     
27a0: 20 20 20 20 20 20 20 20 20 20 20 7b 74 31 20 74             {t1 t
27b0: 32 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24  2}.  test_join $
27c0: 74 6e 2e 31 2e 32 20 20 22 74 31 20 49 4e 4e 45  tn.1.2  "t1 INNE
27d0: 52 20 4a 4f 49 4e 20 74 32 22 20 20 20 20 20 20  R JOIN t2"      
27e0: 7b 74 31 20 74 32 7d 0a 20 20 74 65 73 74 5f 6a  {t1 t2}.  test_j
27f0: 6f 69 6e 20 24 74 6e 2e 31 2e 33 20 20 22 74 31  oin $tn.1.3  "t1
2800: 20 43 52 4f 53 53 20 4a 4f 49 4e 20 74 32 22 20   CROSS JOIN t2" 
2810: 20 20 20 20 20 7b 74 31 20 74 32 7d 0a 20 20 74       {t1 t2}.  t
2820: 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e 34  est_join $tn.1.4
2830: 20 20 22 74 31 20 4a 4f 49 4e 20 74 32 22 20 20    "t1 JOIN t2"  
2840: 20 20 20 20 20 20 20 20 20 20 7b 74 31 20 74 32            {t1 t2
2850: 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74  }.  test_join $t
2860: 6e 2e 31 2e 35 20 20 22 74 32 2c 20 74 33 22 20  n.1.5  "t2, t3" 
2870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7b                 {
2880: 74 32 20 74 33 7d 0a 20 20 74 65 73 74 5f 6a 6f  t2 t3}.  test_jo
2890: 69 6e 20 24 74 6e 2e 31 2e 36 20 20 22 74 32 20  in $tn.1.6  "t2 
28a0: 49 4e 4e 45 52 20 4a 4f 49 4e 20 74 33 22 20 20  INNER JOIN t3"  
28b0: 20 20 20 20 7b 74 32 20 74 33 7d 0a 20 20 74 65      {t2 t3}.  te
28c0: 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e 37 20  st_join $tn.1.7 
28d0: 20 22 74 32 20 43 52 4f 53 53 20 4a 4f 49 4e 20   "t2 CROSS JOIN 
28e0: 74 33 22 20 20 20 20 20 20 7b 74 32 20 74 33 7d  t3"      {t2 t3}
28f0: 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e  .  test_join $tn
2900: 2e 31 2e 38 20 20 22 74 32 20 4a 4f 49 4e 20 74  .1.8  "t2 JOIN t
2910: 33 22 20 20 20 20 20 20 20 20 20 20 20 20 7b 74  3"            {t
2920: 32 20 74 33 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  2 t3}.  test_joi
2930: 6e 20 24 74 6e 2e 31 2e 39 20 20 22 74 32 2c 20  n $tn.1.9  "t2, 
2940: 74 32 20 41 53 20 78 22 20 20 20 20 20 20 20 20  t2 AS x"        
2950: 20 20 20 7b 74 32 20 74 32 7d 0a 20 20 74 65 73     {t2 t2}.  tes
2960: 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 2e 31 30 20  t_join $tn.1.10 
2970: 22 74 32 20 49 4e 4e 45 52 20 4a 4f 49 4e 20 74  "t2 INNER JOIN t
2980: 32 20 41 53 20 78 22 20 7b 74 32 20 74 32 7d 0a  2 AS x" {t2 t2}.
2990: 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e    test_join $tn.
29a0: 31 2e 31 31 20 22 74 32 20 43 52 4f 53 53 20 4a  1.11 "t2 CROSS J
29b0: 4f 49 4e 20 74 32 20 41 53 20 78 22 20 7b 74 32  OIN t2 AS x" {t2
29c0: 20 74 32 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e   t2}.  test_join
29d0: 20 24 74 6e 2e 31 2e 31 32 20 22 74 32 20 4a 4f   $tn.1.12 "t2 JO
29e0: 49 4e 20 74 32 20 41 53 20 78 22 20 20 20 20 20  IN t2 AS x"     
29f0: 20 20 7b 74 32 20 74 32 7d 0a 0a 20 20 23 20 45    {t2 t2}..  # E
2a00: 56 49 44 45 4e 43 45 2d 4f 46 3a 20 52 2d 32 32  VIDENCE-OF: R-22
2a10: 37 37 35 2d 35 36 34 39 36 20 49 66 20 74 68 65  775-56496 If the
2a20: 72 65 20 69 73 20 61 6e 20 4f 4e 20 63 6c 61 75  re is an ON clau
2a30: 73 65 20 73 70 65 63 69 66 69 65 64 2c 20 74 68  se specified, th
2a40: 65 6e 0a 20 20 23 20 74 68 65 20 4f 4e 20 65 78  en.  # the ON ex
2a50: 70 72 65 73 73 69 6f 6e 20 69 73 20 65 76 61 6c  pression is eval
2a60: 75 61 74 65 64 20 66 6f 72 20 65 61 63 68 20 72  uated for each r
2a70: 6f 77 20 6f 66 20 74 68 65 20 63 61 72 74 65 73  ow of the cartes
2a80: 69 61 6e 20 70 72 6f 64 75 63 74 0a 20 20 23 20  ian product.  # 
2a90: 61 73 20 61 20 62 6f 6f 6c 65 61 6e 20 65 78 70  as a boolean exp
2aa0: 72 65 73 73 69 6f 6e 2e 20 41 6c 6c 20 72 6f 77  ression. All row
2ab0: 73 20 66 6f 72 20 77 68 69 63 68 20 74 68 65 20  s for which the 
2ac0: 65 78 70 72 65 73 73 69 6f 6e 20 65 76 61 6c 75  expression evalu
2ad0: 61 74 65 73 0a 20 20 23 20 74 6f 20 66 61 6c 73  ates.  # to fals
2ae0: 65 20 61 72 65 20 65 78 63 6c 75 64 65 64 20 66  e are excluded f
2af0: 72 6f 6d 20 74 68 65 20 64 61 74 61 73 65 74 2e  rom the dataset.
2b00: 0a 20 20 23 0a 20 20 74 65 73 74 5f 6a 6f 69 6e  .  #.  test_join
2b10: 20 24 74 6e 2e 32 2e 31 20 20 22 74 31 2c 20 74   $tn.2.1  "t1, t
2b20: 32 20 4f 4e 20 28 74 31 2e 61 3d 74 32 2e 61 29  2 ON (t1.a=t2.a)
2b30: 22 20 20 7b 74 31 20 74 32 20 2d 6f 6e 20 7b 74  "  {t1 t2 -on {t
2b40: 65 5f 65 71 75 61 6c 73 20 61 20 61 7d 7d 0a 20  e_equals a a}}. 
2b50: 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32   test_join $tn.2
2b60: 2e 32 20 20 22 74 32 2c 20 74 31 20 4f 4e 20 28  .2  "t2, t1 ON (
2b70: 74 31 2e 61 3d 74 32 2e 61 29 22 20 20 7b 74 32  t1.a=t2.a)"  {t2
2b80: 20 74 31 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61   t1 -on {te_equa
2b90: 6c 73 20 61 20 61 7d 7d 0a 20 20 74 65 73 74 5f  ls a a}}.  test_
2ba0: 6a 6f 69 6e 20 24 74 6e 2e 32 2e 33 20 20 22 74  join $tn.2.3  "t
2bb0: 32 2c 20 74 31 20 4f 4e 20 28 31 29 22 20 20 20  2, t1 ON (1)"   
2bc0: 20 20 20 20 20 20 20 7b 74 32 20 74 31 20 2d 6f         {t2 t1 -o
2bd0: 6e 20 74 65 5f 74 72 75 65 7d 0a 20 20 74 65 73  n te_true}.  tes
2be0: 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32 2e 34 20 20  t_join $tn.2.4  
2bf0: 22 74 32 2c 20 74 31 20 4f 4e 20 28 4e 55 4c 4c  "t2, t1 ON (NULL
2c00: 29 22 20 20 20 20 20 20 20 7b 74 32 20 74 31 20  )"       {t2 t1 
2c10: 2d 6f 6e 20 74 65 5f 66 61 6c 73 65 7d 0a 20 20  -on te_false}.  
2c20: 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 32 2e  test_join $tn.2.
2c30: 35 20 20 22 74 32 2c 20 74 31 20 4f 4e 20 28 31  5  "t2, t1 ON (1
2c40: 2e 31 2d 31 2e 31 29 22 20 20 20 20 7b 74 32 20  .1-1.1)"    {t2 
2c50: 74 31 20 2d 6f 6e 20 74 65 5f 66 61 6c 73 65 7d  t1 -on te_false}
2c60: 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e  .  test_join $tn
2c70: 2e 32 2e 36 20 20 22 74 31 2c 20 74 32 20 4f 4e  .2.6  "t1, t2 ON
2c80: 20 28 31 2e 31 2d 31 2e 30 29 22 20 20 20 20 7b   (1.1-1.0)"    {
2c90: 74 31 20 74 32 20 2d 6f 6e 20 74 65 5f 74 72 75  t1 t2 -on te_tru
2ca0: 65 7d 0a 0a 0a 20 20 74 65 73 74 5f 6a 6f 69 6e  e}...  test_join
2cb0: 20 24 74 6e 2e 33 20 22 74 31 20 4c 45 46 54 20   $tn.3 "t1 LEFT 
2cc0: 4a 4f 49 4e 20 74 32 20 4f 4e 20 28 74 31 2e 61  JOIN t2 ON (t1.a
2cd0: 3d 74 32 2e 61 29 22 20 7b 74 31 20 74 32 20 2d  =t2.a)" {t1 t2 -
2ce0: 6c 65 66 74 20 2d 6f 6e 20 7b 74 65 5f 65 71 75  left -on {te_equ
2cf0: 61 6c 73 20 61 20 61 7d 7d 0a 20 20 74 65 73 74  als a a}}.  test
2d00: 5f 6a 6f 69 6e 20 24 74 6e 2e 34 20 22 74 31 20  _join $tn.4 "t1 
2d10: 4c 45 46 54 20 4a 4f 49 4e 20 74 32 20 55 53 49  LEFT JOIN t2 USI
2d20: 4e 47 20 28 61 29 22 20 7b 0a 20 20 20 20 74 31  NG (a)" {.    t1
2d30: 20 74 32 20 2d 6c 65 66 74 20 2d 75 73 69 6e 67   t2 -left -using
2d40: 20 61 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c   a -on {te_equal
2d50: 73 20 61 20 61 7d 0a 20 20 7d 0a 20 20 74 65 73  s a a}.  }.  tes
2d60: 74 5f 6a 6f 69 6e 20 24 74 6e 2e 35 20 22 74 31  t_join $tn.5 "t1
2d70: 20 43 52 4f 53 53 20 4a 4f 49 4e 20 74 32 20 55   CROSS JOIN t2 U
2d80: 53 49 4e 47 28 62 2c 20 61 29 22 20 7b 0a 20 20  SING(b, a)" {.  
2d90: 20 20 74 31 20 74 32 20 2d 75 73 69 6e 67 20 7b    t1 t2 -using {
2da0: 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64  a b} -on {te_and
2db0: 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61 7d   {te_equals a a}
2dc0: 20 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62 7d   {te_equals b b}
2dd0: 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  }.  }.  test_joi
2de0: 6e 20 24 74 6e 2e 36 20 22 74 31 20 4e 41 54 55  n $tn.6 "t1 NATU
2df0: 52 41 4c 20 4a 4f 49 4e 20 74 32 22 20 7b 0a 20  RAL JOIN t2" {. 
2e00: 20 20 20 74 31 20 74 32 20 2d 75 73 69 6e 67 20     t1 t2 -using 
2e10: 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e  {a b} -on {te_an
2e20: 64 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61  d {te_equals a a
2e30: 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62  } {te_equals b b
2e40: 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f  }}.  }.  test_jo
2e50: 69 6e 20 24 74 6e 2e 37 20 22 74 31 20 4e 41 54  in $tn.7 "t1 NAT
2e60: 55 52 41 4c 20 49 4e 4e 45 52 20 4a 4f 49 4e 20  URAL INNER JOIN 
2e70: 74 32 22 20 7b 0a 20 20 20 20 74 31 20 74 32 20  t2" {.    t1 t2 
2e80: 2d 75 73 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e  -using {a b} -on
2e90: 20 7b 74 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75   {te_and {te_equ
2ea0: 61 6c 73 20 61 20 61 7d 20 7b 74 65 5f 65 71 75  als a a} {te_equ
2eb0: 61 6c 73 20 62 20 62 7d 7d 0a 20 20 7d 0a 20 20  als b b}}.  }.  
2ec0: 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 38 20  test_join $tn.8 
2ed0: 22 74 31 20 4e 41 54 55 52 41 4c 20 43 52 4f 53  "t1 NATURAL CROS
2ee0: 53 20 4a 4f 49 4e 20 74 32 22 20 7b 0a 20 20 20  S JOIN t2" {.   
2ef0: 20 74 31 20 74 32 20 2d 75 73 69 6e 67 20 7b 61   t1 t2 -using {a
2f00: 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64 20   b} -on {te_and 
2f10: 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61 7d 20  {te_equals a a} 
2f20: 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62 7d 7d  {te_equals b b}}
2f30: 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e  .  }.  test_join
2f40: 20 24 74 6e 2e 39 20 22 74 31 20 4e 41 54 55 52   $tn.9 "t1 NATUR
2f50: 41 4c 20 49 4e 4e 45 52 20 4a 4f 49 4e 20 74 32  AL INNER JOIN t2
2f60: 22 20 7b 0a 20 20 20 20 74 31 20 74 32 20 2d 75  " {.    t1 t2 -u
2f70: 73 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b  sing {a b} -on {
2f80: 74 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c  te_and {te_equal
2f90: 73 20 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c  s a a} {te_equal
2fa0: 73 20 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65  s b b}}.  }.  te
2fb0: 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 30 20 22  st_join $tn.10 "
2fc0: 74 31 20 4e 41 54 55 52 41 4c 20 4c 45 46 54 20  t1 NATURAL LEFT 
2fd0: 4a 4f 49 4e 20 74 32 22 20 7b 0a 20 20 20 20 74  JOIN t2" {.    t
2fe0: 31 20 74 32 20 2d 6c 65 66 74 20 2d 75 73 69 6e  1 t2 -left -usin
2ff0: 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f  g {a b} -on {te_
3000: 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73 20 61  and {te_equals a
3010: 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20 62   a} {te_equals b
3020: 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f   b}}.  }.  test_
3030: 6a 6f 69 6e 20 24 74 6e 2e 31 31 20 22 74 31 20  join $tn.11 "t1 
3040: 4e 41 54 55 52 41 4c 20 4c 45 46 54 20 4f 55 54  NATURAL LEFT OUT
3050: 45 52 20 4a 4f 49 4e 20 74 32 22 20 7b 0a 20 20  ER JOIN t2" {.  
3060: 20 20 74 31 20 74 32 20 2d 6c 65 66 74 20 2d 75    t1 t2 -left -u
3070: 73 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b  sing {a b} -on {
3080: 74 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c  te_and {te_equal
3090: 73 20 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c  s a a} {te_equal
30a0: 73 20 62 20 62 7d 7d 0a 20 20 7d 0a 20 20 74 65  s b b}}.  }.  te
30b0: 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 32 20 22  st_join $tn.12 "
30c0: 74 32 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20  t2 NATURAL JOIN 
30d0: 74 31 22 20 7b 0a 20 20 20 20 74 32 20 74 31 20  t1" {.    t2 t1 
30e0: 2d 75 73 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e  -using {a b} -on
30f0: 20 7b 74 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75   {te_and {te_equ
3100: 61 6c 73 20 61 20 61 7d 20 7b 74 65 5f 65 71 75  als a a} {te_equ
3110: 61 6c 73 20 62 20 62 7d 7d 0a 20 20 7d 0a 20 20  als b b}}.  }.  
3120: 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 33  test_join $tn.13
3130: 20 22 74 32 20 4e 41 54 55 52 41 4c 20 49 4e 4e   "t2 NATURAL INN
3140: 45 52 20 4a 4f 49 4e 20 74 31 22 20 7b 0a 20 20  ER JOIN t1" {.  
3150: 20 20 74 32 20 74 31 20 2d 75 73 69 6e 67 20 7b    t2 t1 -using {
3160: 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64  a b} -on {te_and
3170: 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61 7d   {te_equals a a}
3180: 20 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62 7d   {te_equals b b}
3190: 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  }.  }.  test_joi
31a0: 6e 20 24 74 6e 2e 31 34 20 22 74 32 20 4e 41 54  n $tn.14 "t2 NAT
31b0: 55 52 41 4c 20 43 52 4f 53 53 20 4a 4f 49 4e 20  URAL CROSS JOIN 
31c0: 74 31 22 20 7b 0a 20 20 20 20 74 32 20 74 31 20  t1" {.    t2 t1 
31d0: 2d 75 73 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e  -using {a b} -on
31e0: 20 7b 74 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75   {te_and {te_equ
31f0: 61 6c 73 20 61 20 61 7d 20 7b 74 65 5f 65 71 75  als a a} {te_equ
3200: 61 6c 73 20 62 20 62 7d 7d 0a 20 20 7d 0a 20 20  als b b}}.  }.  
3210: 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e 31 35  test_join $tn.15
3220: 20 22 74 32 20 4e 41 54 55 52 41 4c 20 49 4e 4e   "t2 NATURAL INN
3230: 45 52 20 4a 4f 49 4e 20 74 31 22 20 7b 0a 20 20  ER JOIN t1" {.  
3240: 20 20 74 32 20 74 31 20 2d 75 73 69 6e 67 20 7b    t2 t1 -using {
3250: 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64  a b} -on {te_and
3260: 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61 7d   {te_equals a a}
3270: 20 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62 7d   {te_equals b b}
3280: 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  }.  }.  test_joi
3290: 6e 20 24 74 6e 2e 31 36 20 22 74 32 20 4e 41 54  n $tn.16 "t2 NAT
32a0: 55 52 41 4c 20 4c 45 46 54 20 4a 4f 49 4e 20 74  URAL LEFT JOIN t
32b0: 31 22 20 7b 0a 20 20 20 20 74 32 20 74 31 20 2d  1" {.    t2 t1 -
32c0: 6c 65 66 74 20 2d 75 73 69 6e 67 20 7b 61 20 62  left -using {a b
32d0: 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64 20 7b 74  } -on {te_and {t
32e0: 65 5f 65 71 75 61 6c 73 20 61 20 61 7d 20 7b 74  e_equals a a} {t
32f0: 65 5f 65 71 75 61 6c 73 20 62 20 62 7d 7d 0a 20  e_equals b b}}. 
3300: 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24   }.  test_join $
3310: 74 6e 2e 31 37 20 22 74 32 20 4e 41 54 55 52 41  tn.17 "t2 NATURA
3320: 4c 20 4c 45 46 54 20 4f 55 54 45 52 20 4a 4f 49  L LEFT OUTER JOI
3330: 4e 20 74 31 22 20 7b 0a 20 20 20 20 74 32 20 74  N t1" {.    t2 t
3340: 31 20 2d 6c 65 66 74 20 2d 75 73 69 6e 67 20 7b  1 -left -using {
3350: 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64  a b} -on {te_and
3360: 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61 7d   {te_equals a a}
3370: 20 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62 7d   {te_equals b b}
3380: 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  }.  }.  test_joi
3390: 6e 20 24 74 6e 2e 31 38 20 22 74 31 20 4c 45 46  n $tn.18 "t1 LEF
33a0: 54 20 4a 4f 49 4e 20 74 32 20 55 53 49 4e 47 20  T JOIN t2 USING 
33b0: 28 62 29 22 20 7b 0a 20 20 20 20 74 31 20 74 32  (b)" {.    t1 t2
33c0: 20 2d 6c 65 66 74 20 2d 75 73 69 6e 67 20 62 20   -left -using b 
33d0: 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 62  -on {te_equals b
33e0: 20 62 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a   b}.  }.  test_j
33f0: 6f 69 6e 20 24 74 6e 2e 31 39 20 22 74 31 20 4a  oin $tn.19 "t1 J
3400: 4f 49 4e 20 74 33 20 55 53 49 4e 47 28 62 29 22  OIN t3 USING(b)"
3410: 20 7b 74 31 20 74 33 20 2d 75 73 69 6e 67 20 62   {t1 t3 -using b
3420: 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20   -on {te_equals 
3430: 62 20 62 7d 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  b b}}.  test_joi
3440: 6e 20 24 74 6e 2e 32 30 20 22 74 33 20 4a 4f 49  n $tn.20 "t3 JOI
3450: 4e 20 74 31 20 55 53 49 4e 47 28 62 29 22 20 7b  N t1 USING(b)" {
3460: 0a 20 20 20 20 74 33 20 74 31 20 2d 75 73 69 6e  .    t3 t1 -usin
3470: 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61  g b -on {te_equa
3480: 6c 73 20 2d 6e 6f 63 61 73 65 20 62 20 62 7d 0a  ls -nocase b b}.
3490: 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20    }.  test_join 
34a0: 24 74 6e 2e 32 31 20 22 74 31 20 4e 41 54 55 52  $tn.21 "t1 NATUR
34b0: 41 4c 20 4a 4f 49 4e 20 74 33 22 20 20 7b 0a 20  AL JOIN t3"  {. 
34c0: 20 20 20 74 31 20 74 33 20 2d 75 73 69 6e 67 20     t1 t3 -using 
34d0: 62 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73  b -on {te_equals
34e0: 20 62 20 62 7d 0a 20 20 7d 0a 20 20 74 65 73 74   b b}.  }.  test
34f0: 5f 6a 6f 69 6e 20 24 74 6e 2e 32 32 20 22 74 33  _join $tn.22 "t3
3500: 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20 74 31   NATURAL JOIN t1
3510: 22 20 20 7b 0a 20 20 20 20 74 33 20 74 31 20 2d  "  {.    t3 t1 -
3520: 75 73 69 6e 67 20 62 20 2d 6f 6e 20 7b 74 65 5f  using b -on {te_
3530: 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 62  equals -nocase b
3540: 20 62 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a   b}.  }.  test_j
3550: 6f 69 6e 20 24 74 6e 2e 32 33 20 22 74 31 20 4e  oin $tn.23 "t1 N
3560: 41 54 55 52 41 4c 20 4c 45 46 54 20 4a 4f 49 4e  ATURAL LEFT JOIN
3570: 20 74 33 22 20 7b 0a 20 20 20 20 74 31 20 74 33   t3" {.    t1 t3
3580: 20 2d 6c 65 66 74 20 2d 75 73 69 6e 67 20 62 20   -left -using b 
3590: 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 62  -on {te_equals b
35a0: 20 62 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a   b}.  }.  test_j
35b0: 6f 69 6e 20 24 74 6e 2e 32 34 20 22 74 33 20 4e  oin $tn.24 "t3 N
35c0: 41 54 55 52 41 4c 20 4c 45 46 54 20 4a 4f 49 4e  ATURAL LEFT JOIN
35d0: 20 74 31 22 20 7b 0a 20 20 20 20 74 33 20 74 31   t1" {.    t3 t1
35e0: 20 2d 6c 65 66 74 20 2d 75 73 69 6e 67 20 62 20   -left -using b 
35f0: 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d  -on {te_equals -
3600: 6e 6f 63 61 73 65 20 62 20 62 7d 0a 20 20 7d 0a  nocase b b}.  }.
3610: 20 20 74 65 73 74 5f 6a 6f 69 6e 20 24 74 6e 2e    test_join $tn.
3620: 32 35 20 22 74 31 20 4c 45 46 54 20 4a 4f 49 4e  25 "t1 LEFT JOIN
3630: 20 74 33 20 4f 4e 20 28 74 33 2e 62 3d 74 31 2e   t3 ON (t3.b=t1.
3640: 62 29 22 20 7b 0a 20 20 20 20 74 31 20 74 33 20  b)" {.    t1 t3 
3650: 2d 6c 65 66 74 20 2d 6f 6e 20 7b 74 65 5f 65 71  -left -on {te_eq
3660: 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 62 20 62  uals -nocase b b
3670: 7d 0a 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69  }.  }.  test_joi
3680: 6e 20 24 74 6e 2e 32 36 20 22 74 31 20 4c 45 46  n $tn.26 "t1 LEF
3690: 54 20 4a 4f 49 4e 20 74 33 20 4f 4e 20 28 74 31  T JOIN t3 ON (t1
36a0: 2e 62 3d 74 33 2e 62 29 22 20 7b 0a 20 20 20 20  .b=t3.b)" {.    
36b0: 74 31 20 74 33 20 2d 6c 65 66 74 20 2d 6f 6e 20  t1 t3 -left -on 
36c0: 7b 74 65 5f 65 71 75 61 6c 73 20 62 20 62 7d 0a  {te_equals b b}.
36d0: 20 20 7d 0a 20 20 74 65 73 74 5f 6a 6f 69 6e 20    }.  test_join 
36e0: 24 74 6e 2e 32 37 20 22 74 31 20 4a 4f 49 4e 20  $tn.27 "t1 JOIN 
36f0: 74 33 20 4f 4e 20 28 74 31 2e 62 3d 74 33 2e 62  t3 ON (t1.b=t3.b
3700: 29 22 20 7b 20 74 31 20 74 33 20 2d 6f 6e 20 7b  )" { t1 t3 -on {
3710: 74 65 5f 65 71 75 61 6c 73 20 62 20 62 7d 20 7d  te_equals b b} }
3720: 0a 0a 20 20 23 20 45 56 49 44 45 4e 43 45 2d 4f  ..  # EVIDENCE-O
3730: 46 3a 20 52 2d 32 38 37 36 30 2d 35 33 38 34 33  F: R-28760-53843
3740: 20 57 68 65 6e 20 6d 6f 72 65 20 74 68 61 6e 20   When more than 
3750: 74 77 6f 20 74 61 62 6c 65 73 20 61 72 65 20 6a  two tables are j
3760: 6f 69 6e 65 64 0a 20 20 23 20 74 6f 67 65 74 68  oined.  # togeth
3770: 65 72 20 61 73 20 70 61 72 74 20 6f 66 20 61 20  er as part of a 
3780: 46 52 4f 4d 20 63 6c 61 75 73 65 2c 20 74 68 65  FROM clause, the
3790: 20 6a 6f 69 6e 20 6f 70 65 72 61 74 69 6f 6e 73   join operations
37a0: 20 61 72 65 20 70 72 6f 63 65 73 73 65 64 0a 20   are processed. 
37b0: 20 23 20 69 6e 20 6f 72 64 65 72 20 66 72 6f 6d   # in order from
37c0: 20 6c 65 66 74 20 74 6f 20 72 69 67 68 74 2e 20   left to right. 
37d0: 49 6e 20 6f 74 68 65 72 20 77 6f 72 64 73 2c 20  In other words, 
37e0: 74 68 65 20 46 52 4f 4d 20 63 6c 61 75 73 65 20  the FROM clause 
37f0: 28 41 0a 20 20 23 20 6a 6f 69 6e 2d 6f 70 2d 31  (A.  # join-op-1
3800: 20 42 20 6a 6f 69 6e 2d 6f 70 2d 32 20 43 29 20   B join-op-2 C) 
3810: 69 73 20 63 6f 6d 70 75 74 65 64 20 61 73 20 28  is computed as (
3820: 28 41 20 6a 6f 69 6e 2d 6f 70 2d 31 20 42 29 20  (A join-op-1 B) 
3830: 6a 6f 69 6e 2d 6f 70 2d 32 20 43 29 2e 0a 20 20  join-op-2 C)..  
3840: 23 0a 20 20 23 20 20 20 54 65 73 74 73 20 32 38  #.  #   Tests 28
3850: 61 20 61 6e 64 20 32 38 62 20 73 68 6f 77 20 74  a and 28b show t
3860: 68 61 74 20 74 68 65 20 73 74 61 74 65 6d 65 6e  hat the statemen
3870: 74 20 61 62 6f 76 65 20 69 73 20 74 72 75 65 20  t above is true 
3880: 66 6f 72 20 74 68 69 73 20 63 61 73 65 2e 0a 20  for this case.. 
3890: 20 23 20 20 20 54 65 73 74 20 32 38 63 20 73 68   #   Test 28c sh
38a0: 6f 77 73 20 74 68 61 74 20 69 66 20 74 68 65 20  ows that if the 
38b0: 70 61 72 65 6e 74 68 65 73 69 73 20 66 6f 72 63  parenthesis forc
38c0: 65 20 61 20 64 69 66 66 65 72 65 6e 74 20 6f 72  e a different or
38d0: 64 65 72 20 6f 66 0a 20 20 23 20 20 20 65 76 61  der of.  #   eva
38e0: 6c 75 61 74 69 6f 6e 20 74 68 65 20 72 65 73 75  luation the resu
38f0: 6c 74 20 69 73 20 64 69 66 66 65 72 65 6e 74 2e  lt is different.
3900: 20 54 65 73 74 20 32 38 64 20 76 65 72 69 66 69   Test 28d verifi
3910: 65 73 20 74 68 61 74 20 74 68 65 20 72 65 73 75  es that the resu
3920: 6c 74 0a 20 20 23 20 20 20 6f 66 20 74 68 65 20  lt.  #   of the 
3930: 71 75 65 72 79 20 77 69 74 68 20 74 68 65 20 70  query with the p
3940: 61 72 65 6e 74 68 65 73 69 73 20 66 6f 72 63 69  arenthesis forci
3950: 6e 67 20 61 20 64 69 66 66 65 72 65 6e 74 20 6f  ng a different o
3960: 72 64 65 72 20 6f 66 20 65 76 61 6c 75 61 74 69  rder of evaluati
3970: 6f 6e 0a 20 20 23 20 20 20 69 73 20 61 73 20 63  on.  #   is as c
3980: 61 6c 63 75 6c 61 74 65 64 20 62 79 20 74 68 65  alculated by the
3990: 20 5b 74 65 5f 2a 5d 20 70 72 6f 63 73 2e 0a 20   [te_*] procs.. 
39a0: 20 23 0a 20 20 73 65 74 20 74 33 5f 6e 61 74 75   #.  set t3_natu
39b0: 72 61 6c 5f 6c 65 66 74 5f 6a 6f 69 6e 5f 74 32  ral_left_join_t2
39c0: 20 5b 0a 20 20 20 20 74 65 5f 74 62 6c 6a 6f 69   [.    te_tbljoi
39d0: 6e 20 64 62 20 74 33 20 74 32 20 2d 6c 65 66 74  n db t3 t2 -left
39e0: 20 2d 75 73 69 6e 67 20 7b 62 7d 20 2d 6f 6e 20   -using {b} -on 
39f0: 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61  {te_equals -noca
3a00: 73 65 20 62 20 62 7d 0a 20 20 5d 0a 20 20 73 65  se b b}.  ].  se
3a10: 74 20 74 31 20 5b 74 65 5f 72 65 61 64 5f 74 62  t t1 [te_read_tb
3a20: 6c 20 64 62 20 74 31 5d 0a 20 20 74 65 5f 64 61  l db t1].  te_da
3a30: 74 61 73 65 74 5f 65 71 5f 75 6e 6f 72 64 65 72  taset_eq_unorder
3a40: 65 64 20 24 74 6e 2e 32 38 61 20 5b 0a 20 20 20  ed $tn.28a [.   
3a50: 20 74 65 5f 72 65 61 64 5f 73 71 6c 20 64 62 20   te_read_sql db 
3a60: 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74  "SELECT * FROM t
3a70: 33 20 4e 41 54 55 52 41 4c 20 4c 45 46 54 20 4a  3 NATURAL LEFT J
3a80: 4f 49 4e 20 74 32 20 4e 41 54 55 52 41 4c 20 4a  OIN t2 NATURAL J
3a90: 4f 49 4e 20 74 31 22 0a 20 20 5d 20 5b 74 65 5f  OIN t1".  ] [te_
3aa0: 6a 6f 69 6e 20 24 74 33 5f 6e 61 74 75 72 61 6c  join $t3_natural
3ab0: 5f 6c 65 66 74 5f 6a 6f 69 6e 5f 74 32 20 24 74  _left_join_t2 $t
3ac0: 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1               
3ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3ae0: 20 5c 0a 20 20 20 20 20 20 2d 75 73 69 6e 67 20   \.      -using 
3af0: 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e  {a b} -on {te_an
3b00: 64 20 7b 74 65 5f 65 71 75 61 6c 73 20 61 20 61  d {te_equals a a
3b10: 7d 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e 6f  } {te_equals -no
3b20: 63 61 73 65 20 62 20 62 7d 7d 20 20 5c 0a 20 20  case b b}}  \.  
3b30: 5d 0a 0a 20 20 74 65 5f 64 61 74 61 73 65 74 5f  ]..  te_dataset_
3b40: 65 71 5f 75 6e 6f 72 64 65 72 65 64 20 24 74 6e  eq_unordered $tn
3b50: 2e 32 38 62 20 5b 0a 20 20 20 20 74 65 5f 72 65  .28b [.    te_re
3b60: 61 64 5f 73 71 6c 20 64 62 20 22 53 45 4c 45 43  ad_sql db "SELEC
3b70: 54 20 2a 20 46 52 4f 4d 20 28 74 33 20 4e 41 54  T * FROM (t3 NAT
3b80: 55 52 41 4c 20 4c 45 46 54 20 4a 4f 49 4e 20 74  URAL LEFT JOIN t
3b90: 32 29 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20  2) NATURAL JOIN 
3ba0: 74 31 22 0a 20 20 5d 20 5b 74 65 5f 6a 6f 69 6e  t1".  ] [te_join
3bb0: 20 24 74 33 5f 6e 61 74 75 72 61 6c 5f 6c 65 66   $t3_natural_lef
3bc0: 74 5f 6a 6f 69 6e 5f 74 32 20 24 74 31 20 20 20  t_join_t2 $t1   
3bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 5c 0a 20               \. 
3bf0: 20 20 20 20 20 2d 75 73 69 6e 67 20 7b 61 20 62       -using {a b
3c00: 7d 20 2d 6f 6e 20 7b 74 65 5f 61 6e 64 20 7b 74  } -on {te_and {t
3c10: 65 5f 65 71 75 61 6c 73 20 61 20 61 7d 20 7b 74  e_equals a a} {t
3c20: 65 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65  e_equals -nocase
3c30: 20 62 20 62 7d 7d 20 20 5c 0a 20 20 5d 0a 0a 20   b b}}  \.  ].. 
3c40: 20 74 65 5f 64 61 74 61 73 65 74 5f 6e 65 5f 75   te_dataset_ne_u
3c50: 6e 6f 72 64 65 72 65 64 20 24 74 6e 2e 32 38 63  nordered $tn.28c
3c60: 20 5b 0a 20 20 20 20 74 65 5f 72 65 61 64 5f 73   [.    te_read_s
3c70: 71 6c 20 64 62 20 22 53 45 4c 45 43 54 20 2a 20  ql db "SELECT * 
3c80: 46 52 4f 4d 20 28 74 33 20 4e 41 54 55 52 41 4c  FROM (t3 NATURAL
3c90: 20 4c 45 46 54 20 4a 4f 49 4e 20 74 32 29 20 4e   LEFT JOIN t2) N
3ca0: 41 54 55 52 41 4c 20 4a 4f 49 4e 20 74 31 22 0a  ATURAL JOIN t1".
3cb0: 20 20 5d 20 5b 0a 20 20 20 20 74 65 5f 72 65 61    ] [.    te_rea
3cc0: 64 5f 73 71 6c 20 64 62 20 22 53 45 4c 45 43 54  d_sql db "SELECT
3cd0: 20 2a 20 46 52 4f 4d 20 74 33 20 4e 41 54 55 52   * FROM t3 NATUR
3ce0: 41 4c 20 4c 45 46 54 20 4a 4f 49 4e 20 28 74 32  AL LEFT JOIN (t2
3cf0: 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20 74 31   NATURAL JOIN t1
3d00: 29 22 0a 20 20 5d 0a 0a 20 20 73 65 74 20 74 32  )".  ]..  set t2
3d10: 5f 6e 61 74 75 72 61 6c 5f 6a 6f 69 6e 5f 74 31  _natural_join_t1
3d20: 20 5b 74 65 5f 74 62 6c 6a 6f 69 6e 20 64 62 20   [te_tbljoin db 
3d30: 74 32 20 74 31 20 2d 75 73 69 6e 67 20 7b 61 20  t2 t1 -using {a 
3d40: 62 7d 20 20 20 20 20 20 20 20 20 20 20 20 20 20  b}              
3d50: 20 20 20 5c 0a 20 20 20 20 20 20 20 20 2d 75 73     \.        -us
3d60: 69 6e 67 20 7b 61 20 62 7d 20 2d 6f 6e 20 7b 74  ing {a b} -on {t
3d70: 65 5f 61 6e 64 20 7b 74 65 5f 65 71 75 61 6c 73  e_and {te_equals
3d80: 20 61 20 61 7d 20 7b 74 65 5f 65 71 75 61 6c 73   a a} {te_equals
3d90: 20 2d 6e 6f 63 61 73 65 20 62 20 62 7d 7d 20 20   -nocase b b}}  
3da0: 5c 0a 20 20 5d 0a 20 20 73 65 74 20 74 33 20 5b  \.  ].  set t3 [
3db0: 74 65 5f 72 65 61 64 5f 74 62 6c 20 64 62 20 74  te_read_tbl db t
3dc0: 33 5d 0a 20 20 74 65 5f 64 61 74 61 73 65 74 5f  3].  te_dataset_
3dd0: 65 71 5f 75 6e 6f 72 64 65 72 65 64 20 24 74 6e  eq_unordered $tn
3de0: 2e 32 38 64 20 5b 0a 20 20 20 20 74 65 5f 72 65  .28d [.    te_re
3df0: 61 64 5f 73 71 6c 20 64 62 20 22 53 45 4c 45 43  ad_sql db "SELEC
3e00: 54 20 2a 20 46 52 4f 4d 20 74 33 20 4e 41 54 55  T * FROM t3 NATU
3e10: 52 41 4c 20 4c 45 46 54 20 4a 4f 49 4e 20 28 74  RAL LEFT JOIN (t
3e20: 32 20 4e 41 54 55 52 41 4c 20 4a 4f 49 4e 20 74  2 NATURAL JOIN t
3e30: 31 29 22 0a 20 20 5d 20 5b 74 65 5f 6a 6f 69 6e  1)".  ] [te_join
3e40: 20 24 74 33 20 24 74 32 5f 6e 61 74 75 72 61 6c   $t3 $t2_natural
3e50: 5f 6a 6f 69 6e 5f 74 31 20 20 20 20 20 20 20 20  _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 5c                 \
3e80: 0a 20 20 20 20 20 20 2d 6c 65 66 74 20 2d 75 73  .      -left -us
3e90: 69 6e 67 20 7b 62 7d 20 2d 6f 6e 20 7b 74 65 5f  ing {b} -on {te_
3ea0: 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 62  equals -nocase b
3eb0: 20 62 7d 20 20 20 20 20 20 20 20 20 20 20 20 20   b}             
3ec0: 20 20 20 20 20 20 20 20 20 20 20 20 5c 0a 20 20              \.  
3ed0: 5d 0a 7d 0a 0a 64 6f 5f 65 78 65 63 73 71 6c 5f  ].}..do_execsql_
3ee0: 74 65 73 74 20 65 5f 73 65 6c 65 63 74 32 2d 32  test e_select2-2
3ef0: 2e 30 20 7b 0a 20 20 43 52 45 41 54 45 20 54 41  .0 {.  CREATE TA
3f00: 42 4c 45 20 74 34 28 78 20 54 45 58 54 20 43 4f  BLE t4(x TEXT CO
3f10: 4c 4c 41 54 45 20 6e 6f 63 61 73 65 29 3b 0a 20  LLATE nocase);. 
3f20: 20 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 35   CREATE TABLE t5
3f30: 28 79 20 49 4e 54 45 47 45 52 2c 20 7a 20 54 45  (y INTEGER, z TE
3f40: 58 54 20 43 4f 4c 4c 41 54 45 20 62 69 6e 61 72  XT COLLATE binar
3f50: 79 29 3b 0a 0a 20 20 49 4e 53 45 52 54 20 49 4e  y);..  INSERT IN
3f60: 54 4f 20 74 34 20 56 41 4c 55 45 53 28 27 32 2e  TO t4 VALUES('2.
3f70: 30 27 29 3b 0a 20 20 49 4e 53 45 52 54 20 49 4e  0');.  INSERT IN
3f80: 54 4f 20 74 34 20 56 41 4c 55 45 53 28 27 54 57  TO t4 VALUES('TW
3f90: 4f 27 29 3b 0a 20 20 49 4e 53 45 52 54 20 49 4e  O');.  INSERT IN
3fa0: 54 4f 20 74 35 20 56 41 4c 55 45 53 28 32 2c 20  TO t5 VALUES(2, 
3fb0: 27 74 77 6f 27 29 3b 0a 7d 20 7b 7d 0a 0a 23 20  'two');.} {}..# 
3fc0: 45 56 49 44 45 4e 43 45 2d 4f 46 3a 20 52 2d 35  EVIDENCE-OF: R-5
3fd0: 35 38 32 34 2d 34 30 39 37 36 20 41 20 73 75 62  5824-40976 A sub
3fe0: 2d 73 65 6c 65 63 74 20 73 70 65 63 69 66 69 65  -select specifie
3ff0: 64 20 69 6e 20 74 68 65 20 6a 6f 69 6e 2d 73 6f  d in the join-so
4000: 75 72 63 65 0a 23 20 66 6f 6c 6c 6f 77 69 6e 67  urce.# following
4010: 20 74 68 65 20 46 52 4f 4d 20 63 6c 61 75 73 65   the FROM clause
4020: 20 69 6e 20 61 20 73 69 6d 70 6c 65 20 53 45 4c   in a simple SEL
4030: 45 43 54 20 73 74 61 74 65 6d 65 6e 74 20 69 73  ECT statement is
4040: 20 68 61 6e 64 6c 65 64 20 61 73 0a 23 20 69 66   handled as.# if
4050: 20 69 74 20 77 61 73 20 61 20 74 61 62 6c 65 20   it was a table 
4060: 63 6f 6e 74 61 69 6e 69 6e 67 20 74 68 65 20 64  containing the d
4070: 61 74 61 20 72 65 74 75 72 6e 65 64 20 62 79 20  ata returned by 
4080: 65 78 65 63 75 74 69 6e 67 20 74 68 65 0a 23 20  executing the.# 
4090: 73 75 62 2d 73 65 6c 65 63 74 20 73 74 61 74 65  sub-select state
40a0: 6d 65 6e 74 2e 0a 23 0a 23 20 45 56 49 44 45 4e  ment..#.# EVIDEN
40b0: 43 45 2d 4f 46 3a 20 52 2d 34 32 36 31 32 2d 30  CE-OF: R-42612-0
40c0: 36 37 35 37 20 45 61 63 68 20 63 6f 6c 75 6d 6e  6757 Each column
40d0: 20 6f 66 20 74 68 65 20 73 75 62 2d 73 65 6c 65   of the sub-sele
40e0: 63 74 20 64 61 74 61 73 65 74 0a 23 20 69 6e 68  ct dataset.# inh
40f0: 65 72 69 74 73 20 74 68 65 20 63 6f 6c 6c 61 74  erits the collat
4100: 69 6f 6e 20 73 65 71 75 65 6e 63 65 20 61 6e 64  ion sequence and
4110: 20 61 66 66 69 6e 69 74 79 20 6f 66 20 74 68 65   affinity of the
4120: 20 63 6f 72 72 65 73 70 6f 6e 64 69 6e 67 0a 23   corresponding.#
4130: 20 65 78 70 72 65 73 73 69 6f 6e 20 69 6e 20 74   expression in t
4140: 68 65 20 73 75 62 2d 73 65 6c 65 63 74 20 73 74  he sub-select st
4150: 61 74 65 6d 65 6e 74 2e 0a 23 0a 66 6f 72 65 61  atement..#.forea
4160: 63 68 20 7b 74 6e 20 73 75 62 73 65 6c 65 63 74  ch {tn subselect
4170: 20 73 65 6c 65 63 74 20 73 70 65 63 7d 20 7b 0a   select spec} {.
4180: 20 20 31 20 20 20 22 53 45 4c 45 43 54 20 2a 20    1   "SELECT * 
4190: 46 52 4f 4d 20 74 32 22 20 20 20 22 53 45 4c 45  FROM t2"   "SELE
41a0: 43 54 20 2a 20 46 52 4f 4d 20 74 31 20 4a 4f 49  CT * FROM t1 JOI
41b0: 4e 20 25 73 73 25 22 20 0a 20 20 20 20 20 20 7b  N %ss%" .      {
41c0: 74 31 20 25 73 73 25 7d 0a 0a 20 20 32 20 20 20  t1 %ss%}..  2   
41d0: 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74  "SELECT * FROM t
41e0: 32 22 20 20 20 22 53 45 4c 45 43 54 20 2a 20 46  2"   "SELECT * F
41f0: 52 4f 4d 20 74 31 20 4a 4f 49 4e 20 25 73 73 25  ROM t1 JOIN %ss%
4200: 20 41 53 20 78 20 4f 4e 20 28 74 31 2e 61 3d 78   AS x ON (t1.a=x
4210: 2e 61 29 22 20 0a 20 20 20 20 20 20 7b 74 31 20  .a)" .      {t1 
4220: 25 73 73 25 20 2d 6f 6e 20 7b 74 65 5f 65 71 75  %ss% -on {te_equ
4230: 61 6c 73 20 30 20 30 7d 7d 0a 0a 20 20 33 20 20  als 0 0}}..  3  
4240: 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20   "SELECT * FROM 
4250: 74 32 22 20 20 20 22 53 45 4c 45 43 54 20 2a 20  t2"   "SELECT * 
4260: 46 52 4f 4d 20 25 73 73 25 20 41 53 20 78 20 4a  FROM %ss% AS x J
4270: 4f 49 4e 20 74 31 20 4f 4e 20 28 74 31 2e 61 3d  OIN t1 ON (t1.a=
4280: 78 2e 61 29 22 20 0a 20 20 20 20 20 20 7b 25 73  x.a)" .      {%s
4290: 73 25 20 74 31 20 2d 6f 6e 20 7b 74 65 5f 65 71  s% t1 -on {te_eq
42a0: 75 61 6c 73 20 30 20 30 7d 7d 0a 0a 20 20 34 20  uals 0 0}}..  4 
42b0: 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d    "SELECT * FROM
42c0: 20 74 31 2c 20 74 32 22 20 22 53 45 4c 45 43 54   t1, t2" "SELECT
42d0: 20 2a 20 46 52 4f 4d 20 25 73 73 25 20 41 53 20   * FROM %ss% AS 
42e0: 78 20 4a 4f 49 4e 20 74 33 22 0a 20 20 20 20 20  x JOIN t3".     
42f0: 20 7b 25 73 73 25 20 74 33 7d 0a 0a 20 20 35 20   {%ss% t3}..  5 
4300: 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d    "SELECT * FROM
4310: 20 74 31 2c 20 74 32 22 20 22 53 45 4c 45 43 54   t1, t2" "SELECT
4320: 20 2a 20 46 52 4f 4d 20 25 73 73 25 20 4e 41 54   * FROM %ss% NAT
4330: 55 52 41 4c 20 4a 4f 49 4e 20 74 33 22 0a 20 20  URAL JOIN t3".  
4340: 20 20 20 20 7b 25 73 73 25 20 74 33 20 2d 75 73      {%ss% t3 -us
4350: 69 6e 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71  ing b -on {te_eq
4360: 75 61 6c 73 20 31 20 30 7d 7d 0a 0a 20 20 36 20  uals 1 0}}..  6 
4370: 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d    "SELECT * FROM
4380: 20 74 31 2c 20 74 32 22 20 22 53 45 4c 45 43 54   t1, t2" "SELECT
4390: 20 2a 20 46 52 4f 4d 20 74 33 20 4e 41 54 55 52   * FROM t3 NATUR
43a0: 41 4c 20 4a 4f 49 4e 20 25 73 73 25 22 0a 20 20  AL JOIN %ss%".  
43b0: 20 20 20 20 7b 74 33 20 25 73 73 25 20 2d 75 73      {t3 %ss% -us
43c0: 69 6e 67 20 62 20 2d 6f 6e 20 7b 74 65 5f 65 71  ing b -on {te_eq
43d0: 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20 30 20 31  uals -nocase 0 1
43e0: 7d 7d 0a 0a 20 20 37 20 20 20 22 53 45 4c 45 43  }}..  7   "SELEC
43f0: 54 20 2a 20 46 52 4f 4d 20 74 31 2c 20 74 32 22  T * FROM t1, t2"
4400: 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20   "SELECT * FROM 
4410: 74 33 20 4e 41 54 55 52 41 4c 20 4c 45 46 54 20  t3 NATURAL LEFT 
4420: 4a 4f 49 4e 20 25 73 73 25 22 0a 20 20 20 20 20  JOIN %ss%".     
4430: 20 7b 74 33 20 25 73 73 25 20 2d 6c 65 66 74 20   {t3 %ss% -left 
4440: 2d 75 73 69 6e 67 20 62 20 2d 6f 6e 20 7b 74 65  -using b -on {te
4450: 5f 65 71 75 61 6c 73 20 2d 6e 6f 63 61 73 65 20  _equals -nocase 
4460: 30 20 31 7d 7d 0a 0a 20 20 38 20 20 20 22 53 45  0 1}}..  8   "SE
4470: 4c 45 43 54 20 63 6f 75 6e 74 28 2a 29 20 41 53  LECT count(*) AS
4480: 20 79 20 46 52 4f 4d 20 74 34 22 20 20 20 22 53   y FROM t4"   "S
4490: 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74 35 2c  ELECT * FROM t5,
44a0: 20 25 73 73 25 20 55 53 49 4e 47 20 28 79 29 22   %ss% USING (y)"
44b0: 0a 20 20 20 20 20 20 7b 74 35 20 25 73 73 25 20  .      {t5 %ss% 
44c0: 2d 75 73 69 6e 67 20 79 20 2d 6f 6e 20 7b 74 65  -using y -on {te
44d0: 5f 65 71 75 61 6c 73 20 2d 61 66 66 69 6e 69 74  _equals -affinit
44e0: 79 20 74 65 78 74 20 30 20 30 7d 7d 0a 0a 20 20  y text 0 0}}..  
44f0: 39 20 20 20 22 53 45 4c 45 43 54 20 63 6f 75 6e  9   "SELECT coun
4500: 74 28 2a 29 20 41 53 20 79 20 46 52 4f 4d 20 74  t(*) AS y FROM t
4510: 34 22 20 20 20 22 53 45 4c 45 43 54 20 2a 20 46  4"   "SELECT * F
4520: 52 4f 4d 20 25 73 73 25 2c 20 74 35 20 55 53 49  ROM %ss%, t5 USI
4530: 4e 47 20 28 79 29 22 0a 20 20 20 20 20 20 7b 25  NG (y)".      {%
4540: 73 73 25 20 74 35 20 2d 75 73 69 6e 67 20 79 20  ss% t5 -using y 
4550: 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d  -on {te_equals -
4560: 61 66 66 69 6e 69 74 79 20 74 65 78 74 20 30 20  affinity text 0 
4570: 30 7d 7d 0a 0a 20 20 31 30 20 20 22 53 45 4c 45  0}}..  10  "SELE
4580: 43 54 20 78 20 41 53 20 79 20 46 52 4f 4d 20 74  CT x AS y FROM t
4590: 34 22 20 20 20 22 53 45 4c 45 43 54 20 2a 20 46  4"   "SELECT * F
45a0: 52 4f 4d 20 25 73 73 25 20 4a 4f 49 4e 20 74 35  ROM %ss% JOIN t5
45b0: 20 55 53 49 4e 47 20 28 79 29 22 0a 20 20 20 20   USING (y)".    
45c0: 20 20 7b 25 73 73 25 20 74 35 20 2d 75 73 69 6e    {%ss% t5 -usin
45d0: 67 20 79 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61  g y -on {te_equa
45e0: 6c 73 20 2d 6e 6f 63 61 73 65 20 2d 61 66 66 69  ls -nocase -affi
45f0: 6e 69 74 79 20 69 6e 74 65 67 65 72 20 30 20 30  nity integer 0 0
4600: 7d 7d 0a 0a 20 20 31 31 20 20 22 53 45 4c 45 43  }}..  11  "SELEC
4610: 54 20 78 20 41 53 20 79 20 46 52 4f 4d 20 74 34  T x AS y FROM t4
4620: 22 20 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52  "   "SELECT * FR
4630: 4f 4d 20 74 35 20 4a 4f 49 4e 20 25 73 73 25 20  OM t5 JOIN %ss% 
4640: 55 53 49 4e 47 20 28 79 29 22 0a 20 20 20 20 20  USING (y)".     
4650: 20 7b 74 35 20 25 73 73 25 20 2d 75 73 69 6e 67   {t5 %ss% -using
4660: 20 79 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c   y -on {te_equal
4670: 73 20 2d 6e 6f 63 61 73 65 20 2d 61 66 66 69 6e  s -nocase -affin
4680: 69 74 79 20 69 6e 74 65 67 65 72 20 30 20 30 7d  ity integer 0 0}
4690: 7d 0a 0a 20 20 31 32 20 20 22 53 45 4c 45 43 54  }..  12  "SELECT
46a0: 20 79 20 41 53 20 78 20 46 52 4f 4d 20 74 35 22   y AS x FROM t5"
46b0: 20 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f     "SELECT * FRO
46c0: 4d 20 25 73 73 25 20 4a 4f 49 4e 20 74 34 20 55  M %ss% JOIN t4 U
46d0: 53 49 4e 47 20 28 78 29 22 0a 20 20 20 20 20 20  SING (x)".      
46e0: 7b 25 73 73 25 20 74 34 20 2d 75 73 69 6e 67 20  {%ss% t4 -using 
46f0: 78 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73  x -on {te_equals
4700: 20 2d 6e 6f 63 61 73 65 20 2d 61 66 66 69 6e 69   -nocase -affini
4710: 74 79 20 69 6e 74 65 67 65 72 20 30 20 30 7d 7d  ty integer 0 0}}
4720: 0a 0a 20 20 31 33 20 20 22 53 45 4c 45 43 54 20  ..  13  "SELECT 
4730: 79 20 41 53 20 78 20 46 52 4f 4d 20 74 35 22 20  y AS x FROM t5" 
4740: 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d    "SELECT * FROM
4750: 20 74 34 20 4a 4f 49 4e 20 25 73 73 25 20 55 53   t4 JOIN %ss% US
4760: 49 4e 47 20 28 78 29 22 0a 20 20 20 20 20 20 7b  ING (x)".      {
4770: 74 34 20 25 73 73 25 20 2d 75 73 69 6e 67 20 78  t4 %ss% -using x
4780: 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20   -on {te_equals 
4790: 2d 6e 6f 63 61 73 65 20 2d 61 66 66 69 6e 69 74  -nocase -affinit
47a0: 79 20 69 6e 74 65 67 65 72 20 30 20 30 7d 7d 0a  y integer 0 0}}.
47b0: 0a 20 20 31 34 20 20 22 53 45 4c 45 43 54 20 2b  .  14  "SELECT +
47c0: 79 20 41 53 20 78 20 46 52 4f 4d 20 74 35 22 20  y AS x FROM t5" 
47d0: 20 20 22 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d    "SELECT * FROM
47e0: 20 25 73 73 25 20 4a 4f 49 4e 20 74 34 20 55 53   %ss% JOIN t4 US
47f0: 49 4e 47 20 28 78 29 22 0a 20 20 20 20 20 20 7b  ING (x)".      {
4800: 25 73 73 25 20 74 34 20 2d 75 73 69 6e 67 20 78  %ss% t4 -using x
4810: 20 2d 6f 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20   -on {te_equals 
4820: 2d 6e 6f 63 61 73 65 20 2d 61 66 66 69 6e 69 74  -nocase -affinit
4830: 79 20 74 65 78 74 20 30 20 30 7d 7d 0a 0a 20 20  y text 0 0}}..  
4840: 31 35 20 20 22 53 45 4c 45 43 54 20 2b 79 20 41  15  "SELECT +y A
4850: 53 20 78 20 46 52 4f 4d 20 74 35 22 20 20 20 22  S x FROM t5"   "
4860: 53 45 4c 45 43 54 20 2a 20 46 52 4f 4d 20 74 34  SELECT * FROM t4
4870: 20 4a 4f 49 4e 20 25 73 73 25 20 55 53 49 4e 47   JOIN %ss% USING
4880: 20 28 78 29 22 0a 20 20 20 20 20 20 7b 74 34 20   (x)".      {t4 
4890: 25 73 73 25 20 2d 75 73 69 6e 67 20 78 20 2d 6f  %ss% -using x -o
48a0: 6e 20 7b 74 65 5f 65 71 75 61 6c 73 20 2d 6e 6f  n {te_equals -no
48b0: 63 61 73 65 20 2d 61 66 66 69 6e 69 74 79 20 74  case -affinity t
48c0: 65 78 74 20 30 20 30 7d 7d 0a 7d 20 7b 0a 0a 20  ext 0 0}}.} {.. 
48d0: 20 23 20 43 72 65 61 74 65 20 61 20 74 65 6d 70   # Create a temp
48e0: 6f 72 61 72 79 20 74 61 62 6c 65 20 6e 61 6d 65  orary table name
48f0: 64 20 25 73 73 25 20 63 6f 6e 74 61 69 6e 69 6e  d %ss% containin
4900: 67 20 74 68 65 20 64 61 74 61 20 72 65 74 75 72  g the data retur
4910: 6e 65 64 20 62 79 0a 20 20 23 20 74 68 65 20 73  ned by.  # the s
4920: 75 62 2d 73 65 6c 65 63 74 2e 20 54 68 65 6e 20  ub-select. Then 
4930: 68 61 76 65 20 74 68 65 20 5b 74 65 5f 74 62 6c  have the [te_tbl
4940: 6a 6f 69 6e 5d 20 70 72 6f 63 20 75 73 65 20 74  join] proc use t
4950: 68 69 73 20 74 61 62 6c 65 20 74 6f 0a 20 20 23  his table to.  #
4960: 20 63 6f 6d 70 75 74 65 20 74 68 65 20 65 78 70   compute the exp
4970: 65 63 74 65 64 20 72 65 73 75 6c 74 73 20 6f 66  ected results of
4980: 20 74 68 65 20 24 73 65 6c 65 63 74 20 71 75 65   the $select que
4990: 72 79 2e 20 44 72 6f 70 20 74 68 65 20 74 65 6d  ry. Drop the tem
49a0: 70 6f 72 61 72 79 0a 20 20 23 20 74 61 62 6c 65  porary.  # table
49b0: 20 62 65 66 6f 72 65 20 63 6f 6e 74 69 6e 75 69   before continui
49c0: 6e 67 2e 0a 20 20 23 0a 20 20 65 78 65 63 73 71  ng..  #.  execsq
49d0: 6c 20 22 43 52 45 41 54 45 20 54 45 4d 50 20 54  l "CREATE TEMP T
49e0: 41 42 4c 45 20 27 25 73 73 25 27 20 41 53 20 24  ABLE '%ss%' AS $
49f0: 73 75 62 73 65 6c 65 63 74 22 0a 20 20 73 65 74  subselect".  set
4a00: 20 74 65 20 5b 65 76 61 6c 20 74 65 5f 74 62 6c   te [eval te_tbl
4a10: 6a 6f 69 6e 20 64 62 20 24 73 70 65 63 5d 0a 20  join db $spec]. 
4a20: 20 65 78 65 63 73 71 6c 20 22 44 52 4f 50 20 54   execsql "DROP T
4a30: 41 42 4c 45 20 27 25 73 73 25 27 22 0a 0a 20 20  ABLE '%ss%'"..  
4a40: 23 20 43 68 65 63 6b 20 74 68 61 74 20 74 68 65  # Check that the
4a50: 20 61 63 74 75 61 6c 20 64 61 74 61 20 72 65 74   actual data ret
4a60: 75 72 6e 65 64 20 62 79 20 74 68 65 20 24 73 65  urned by the $se
4a70: 6c 65 63 74 20 71 75 65 72 79 20 69 73 20 74 68  lect query is th
4a80: 65 20 73 61 6d 65 0a 20 20 23 20 61 73 20 74 68  e same.  # as th
4a90: 65 20 65 78 70 65 63 74 65 64 20 64 61 74 61 20  e expected data 
4aa0: 63 61 6c 63 75 6c 61 74 65 64 20 75 73 69 6e 67  calculated using
4ab0: 20 5b 74 65 5f 74 62 6c 6a 6f 69 6e 5d 20 61 62   [te_tbljoin] ab
4ac0: 6f 76 65 2e 0a 20 20 23 0a 20 20 74 65 5f 64 61  ove..  #.  te_da
4ad0: 74 61 73 65 74 5f 65 71 5f 75 6e 6f 72 64 65 72  taset_eq_unorder
4ae0: 65 64 20 65 5f 73 65 6c 65 63 74 32 2d 32 2e 31  ed e_select2-2.1
4af0: 2e 24 74 6e 20 5b 0a 20 20 20 20 74 65 5f 72 65  .$tn [.    te_re
4b00: 61 64 5f 73 71 6c 20 64 62 20 5b 73 74 72 69 6e  ad_sql db [strin
4b10: 67 20 6d 61 70 20 5b 6c 69 73 74 20 25 73 73 25  g map [list %ss%
4b20: 20 22 28 24 73 75 62 73 65 6c 65 63 74 29 22 5d   "($subselect)"]
4b30: 20 24 73 65 6c 65 63 74 5d 0a 20 20 5d 20 24 74   $select].  ] $t
4b40: 65 0a 7d 0a 0a 66 69 6e 69 73 68 5f 74 65 73 74  e.}..finish_test
4b50: 0a                                               .