/*
 * AbstractTableTest class.
 *
 * Copyright (C) 2007 SATOH Takayuki All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package ts.util.table;

import ts.tester.function.coverage.FunctionTester;
import ts.tester.function.print.*;
import ts.util.*;
import java.util.*;

/**
 * {@link ts.util.table.AbstractTable AbstractTable}クラスの機能試験クラス。
 *
 * @author  佐藤隆之.
 * @version $Revision: 1.2 $, $Date: 2011-08-01 16:07:34 $
 */
public class AbstractTableTest extends FunctionTester
{
  public static void main(String[] args)
  {
    try {
      PrinterGroup group = new PrinterGroup();
      group.addPrinter(new ConsolePrinter());
      group.addPrinter(new HtmlPrinter("SATOH Takayuki"));
      setPrinter(group);

      run(AbstractTableTest.class, (args.length == 0) ? null : args[0]);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  protected void preTesting()
  {
    MSG("AbstractTable クラスの機能試験を実行する。");
  }

  static class TableEx<C,V> extends AbstractTable<C,V> implements Cloneable {
    final static long serialVersionUID = 0L;
    public TableEx() {}
    public TableEx(int nrec, int ncol) { super(nrec, ncol); }
    public TableEx(Header<C> h) { super(h); }
    @Override
    protected Header<C> createHeader(int nc) {
      return new Header<C>() {
        static final long serialVersionUID = 0L;
        Set<C> columnSet_ = new HashSet<C>();
        public int columnCount() { return columnSet_.size(); }
        public Enumeration<C> columns() {
          return Collections.enumeration(columnSet_);
        }
        public boolean hasColumn(Object c) { return columnSet_.contains(c); }
        public void addColumn(C c) { columnSet_.add(c); }
      };
    }
    @Override
    protected Record<C,V> createRecord(int nc) {
      return new Record<C,V>() {
        static final long serialVersionUID = 0L;
        private Map<C,V> map_ = new HashMap<C,V>();
        protected Header<C> header() { return TableEx.this.header(); }
        protected V getValue(Object c) { return map_.get(c); }
        protected V putValue(C c, V v) { return map_.put(c, v); }
        protected V removeValue(Object c) { return map_.remove(c); }
      };
    }
    @Override
    protected Collection<Record<C,V>> createRecordCollection(int nc) {
      return new LinkedList<Record<C,V>>();
    }
  }

  static class TriggerEx<C,V> extends Trigger<C,V> {
    static final long serialVersionUID = -1L;
    private Map<String,String> triggerLogMap = new HashMap<String,String>();
    public TriggerEx(Map<String,String> logMap) {
      triggerLogMap = logMap;
    }
    @Override protected void preAppend(Table<C,V> t, Map<C,V> r) {
      triggerLogMap.put("preAppend", triggerLogMap.get("preAppend") + "#");
    }
    @Override protected void postAppend(Table<C,V> t, Map<C,V> r) {
      triggerLogMap.put("postAppend", triggerLogMap.get("postAppend") + "$");
    }
    @Override protected void preUpdate(Table<C,V> t, Map<C,V> r, Map<C,V> d) {
      triggerLogMap.put("preUpdate",
        triggerLogMap.get("preUpdate") + map2string(d));
    }
    @Override protected void postUpdate(Table<C,V> t, Map<C,V> r, Map<C,V> d) {
      triggerLogMap.put("postUpdate",
        triggerLogMap.get("postUpdate") + map2string(d));
    }
    @Override protected void preDelete(Table<C,V> t, Map<C,V> r) {
      triggerLogMap.put("preDelete", triggerLogMap.get("preDelete") + "%");
    }
    @Override protected void postDelete(Table<C,V> t, Map<C,V> r) {
      triggerLogMap.put("postDelete", triggerLogMap.get("postDelete") + "&");
    }
    String map2string(Map<C,V> m) {
      StringBuffer buf = new StringBuffer("{");
      List<C> l = new LinkedList<C>(m.keySet());
      Collections.sort(l, new GeneralComparator());
      Iterator<C> i = l.iterator();
      if (i.hasNext()) {
        C k = i.next();
        buf.append(k + "=" + m.get(k));
        while (i.hasNext()) {
          k = i.next();
          buf.append(", ").append(k + "=" + m.get(k));
        }
      }
      return buf.append("}").toString();
    }
  };

  /* -- test case -- */

  public void constructor()
  {
    MSG("デフォルト・コンストラクタ。");

    Table<String,String> t = new TableEx<String,String>();
    NOTNULL(t);
  }

  public void constructor_int_int()
  {
    MSG("初期レコード容量と初期カラム容量を引数にとるコンストラクタ。");

    Table<String,Integer> t = new TableEx<String,Integer>(100, 12);
    NOTNULL(t);
  }

  public void constructor_int_int_1()
  {
    MSG("引数が負の値の場合。");

    try {
      Table<String,String> t = new TableEx<String,String>(-1, 12);
      NG();
    }
    catch (AssertionError e) {
      OK(e);
    }

    try {
      Table<String,String> t = new TableEx<String,String>(100, -12);
      NG();
    }
    catch (AssertionError e) {
      OK(e);
    }
  }

  public void constructor_int_int_2()
  {
    MSG("引数の値がゼロの場合。");

    Table<String,Object> t = new TableEx<String,Object>(0, 0);
    NOTNULL(t);
  }

  public void constructor_header()
  {
    MSG("ヘッダを引数にとるコンストラクタ。");

    TableEx<String,String> t1 = new TableEx<String,String>();
    TableEx<String,String> t2 = new TableEx<String,String>(t1.header());
    IDENTIFY(t1.header(), t2.header());
  }

  public void constructor_header_1()
  {
    MSG("引数がヌルの場合。");

    try {
      new TableEx<String,String>(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void columnCount()
  {
    MSG("カラム数の取得。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(t.columnCount(), 0);

    r.put("c0", null);
    EQUAL(t.columnCount(), 1);

    r.put("c1", null);
    EQUAL(t.columnCount(), 2);

    r.put("c2", null);
    EQUAL(t.columnCount(), 3);
  }

  public void recordCount()
  {
    MSG("レコード数の取得。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.recordCount(), 0);

    t.appendNew();
    EQUAL(t.recordCount(), 1);

    t.appendNew();
    EQUAL(t.recordCount(), 2);

    t.appendNew();
    EQUAL(t.recordCount(), 3);

    t.deleteAll();
    EQUAL(t.recordCount(), 0);
  }

  public void columns()
  {
    MSG("カラム・キーの列挙。");

    TableEx<String,String> t = new TableEx<String,String>();
    FALSE(t.columns().hasMoreElements());

    Map<String,String> r0 = t.appendNew();
    FALSE(t.columns().hasMoreElements());

    r0.put("c0", null);
    Enumeration<String> e0 = t.columns();
    TRUE(e0.hasMoreElements());
    EQUAL(e0.nextElement(), "c0");
    FALSE(e0.hasMoreElements());

    r0.put("c1", null);
    Enumeration<String> e1 = t.columns();
    Set<String> s1 = new HashSet<String>();
    TRUE(e1.hasMoreElements());
    s1.add(e1.nextElement());
    TRUE(e1.hasMoreElements());
    s1.add(e1.nextElement());
    FALSE(e1.hasMoreElements());
    EQUAL(s1, r0.keySet());

    r0.put("c2", null);
    Enumeration<String> e2 = t.columns();
    Set<String> s2 = new HashSet<String>();
    TRUE(e2.hasMoreElements());
    s2.add(e2.nextElement());
    TRUE(e2.hasMoreElements());
    s2.add(e2.nextElement());
    TRUE(e2.hasMoreElements());
    s2.add(e2.nextElement());
    FALSE(e2.hasMoreElements());
    EQUAL(s2, r0.keySet());
  }

  public void records()
  {
    MSG("レコードの列挙。");

    TableEx<String,Object> t = new TableEx<String,Object>();
    FALSE(t.records().hasNext());

    Set<Map<String,Object>> s = new IdentityHashSet<Map<String,Object>>();

    Map<String,Object> r0 = t.appendNew();
    r0.put("c0", "a0");
    r0.put("c1", "b0");
    r0.put("c2", "c0");
    s.add(r0);

    MapIterator<String,Object> it0 = t.records();
    TRUE(it0.hasNext());
    EQUAL(it0.next(), r0);
    FALSE(it0.hasNext());

    Map<String,Object> r1 = t.appendNew();
    r1.put("c0", "a1");
    r1.put("c1", "b0");
    s.add(r1);

    Set<Map<String,Object>> s1 = new IdentityHashSet<Map<String,Object>>();
    MapIterator<String,Object> it1 = t.records();
    TRUE(it1.hasNext());
    s1.add(it1.next());
    TRUE(it1.hasNext());
    s1.add(it1.next());
    FALSE(it1.hasNext());
    EQUAL(s1, s);

    Map<String,Object> r2 = t.appendNew();
    r2.put("c0", "a1");
    r2.put("c2", "c2");
    s.add(r2);

    Set<Map<String,Object>> s2 = new IdentityHashSet<Map<String,Object>>();
    MapIterator<String,Object> it2 = t.records();
    TRUE(it2.hasNext());
    s2.add(it2.next());
    TRUE(it2.hasNext());
    s2.add(it2.next());
    TRUE(it2.hasNext());
    s2.add(it2.next());
    FALSE(it2.hasNext());
    EQUAL(s2, s);

    Set<Map<String,Object>> s3 = new IdentityHashSet<Map<String,Object>>();
    MapIterator<String,Object> it3 = t.records();
    TRUE(it3.hasNext());
    s3.add(it3.next());
    it3.remove();
    EQUAL(t.recordCount(), 2);
    TRUE(it3.hasNext());
    s3.add(it3.next());
    it3.remove();
    EQUAL(t.recordCount(), 1);
    TRUE(it3.hasNext());
    s3.add(it3.next());
    it3.remove();
    EQUAL(t.recordCount(), 0);
    FALSE(it3.hasNext());
    EQUAL(s3, s);
  }

  public void records_comparator()
  {
    MSG("レコードをソートして列挙。");

    DefaultMapComparator<String,Object> cmp;
    cmp = new DefaultMapComparator<String,Object>();
    cmp.addKey("c0");
    cmp.addKey("c1");
    cmp.addKey("c2");

    TableEx<String,Object> t = new TableEx<String,Object>();
    FALSE(t.records(cmp).hasNext());

    Set<Map<String,Object>> s = new IdentityHashSet<Map<String,Object>>();

    Map<String,Object> r0 = t.appendNew();
    r0.put("c0", "a0");
    r0.put("c1", "b0");
    r0.put("c2", "c0");
    s.add(r0);

    MapIterator<String,Object> it0 = t.records(cmp);
    Set<Map<String,Object>> s0 = new IdentityHashSet<Map<String,Object>>();
    TRUE(it0.hasNext());
    s0.add(it0.next());
    FALSE(it0.hasNext());
    EQUAL(s0, s);

    Map<String,Object> r1 = t.appendNew();
    r1.put("c0", "a1");
    r1.put("c1", "b0");
    s.add(r1);

    MapIterator<String,Object> it1 = t.records(cmp);
    Set<Map<String,Object>> s1 = new IdentityHashSet<Map<String,Object>>();
    TRUE(it1.hasNext());
    s1.add(it1.next());
    TRUE(it1.hasNext());
    s1.add(it1.next());
    FALSE(it1.hasNext());
    EQUAL(s1, s);

    Map<String,Object> r2 = t.appendNew();
    r2.put("c0", "a1");
    r2.put("c2", "c2");
    s.add(r2);

    MapIterator<String,Object> it2 = t.records(cmp);
    Set<Map<String,Object>> s2 = new IdentityHashSet<Map<String,Object>>();
    TRUE(it2.hasNext());
    s2.add(it2.next());
    TRUE(it2.hasNext());
    s2.add(it2.next());
    TRUE(it2.hasNext());
    s2.add(it2.next());
    FALSE(it2.hasNext());
    EQUAL(s2, s);

    MapIterator<String,Object> it3 = t.records(cmp);
    Set<Map<String,Object>> s3 = new IdentityHashSet<Map<String,Object>>();
    TRUE(it3.hasNext());
    s3.add(it3.next());
    it3.remove();
    EQUAL(t.recordCount(), 2);
    TRUE(it3.hasNext());
    s3.add(it3.next());
    it3.remove();
    EQUAL(t.recordCount(), 1);
    TRUE(it3.hasNext());
    s3.add(it3.next());
    it3.remove();
    EQUAL(t.recordCount(), 0);
    FALSE(it3.hasNext());
    EQUAL(s3, s);
  }

  public void records_comparator_1()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,Object> t = new TableEx<String,Object>();
    try {
      t.records(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void recordFirst()
  {
    MSG("最初のレコードを取得する。");

    TableEx<String,Object> t = new TableEx<String,Object>();
    NULL(t.recordFirst());

    Map<String,Object> r = t.appendNew();
    IDENTIFY(r, t.recordFirst());

    t.appendNew();
    t.appendNew();
    t.appendNew();
    IDENTIFY(r, t.recordFirst());
  }

  public void appendNew()
  {
    MSG("レコードを追加。");
    MSG("空のテーブルにレコードを追加。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    for (int i=0; i<10; i++) {
      t.appendNew();
      EQUAL(t.recordCount(), i+1);
      EQUAL(t.columnCount(), 0);
    }
  }

  public void appendNew_1()
  {
    MSG("追加したレコードに対してputメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    TRUE(r.isEmpty());
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);
    FALSE(r.containsKey(null));
    FALSE(r.containsValue(null));

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);
    TRUE(r.containsKey("C0"));
    TRUE(r.containsValue("V0"));

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    TRUE(r.containsKey("C1"));
    TRUE(r.containsValue("V1"));

    Set<String> s = new HashSet<String>();
    s.add("C0");
    s.add("C1");
    EQUAL(s, r.keySet());

    Set<String> s1 = new HashSet<String>();
    Enumeration<String> e1 = t.columns();
    while (e1.hasMoreElements()) {
      s1.add(e1.nextElement());
    }
    EQUAL(s, s1);
  }

  public void appendNew_2()
  {
    MSG("追加したレコードに対してremoveメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    EQUAL(r.remove("C0"), "V0");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(r.get("C0"), null);
  }

  public void appendNew_3()
  {
    MSG("追加したレコードに対してputAllメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    Map<String,String> m = new HashMap<String,String>();
    m.put("C0", "あいうえお");
    m.put("C1", "かきくけこ");
    m.put("C2", "さしすせそ");

    r.putAll(m);
    EQUAL(r.size(), 3);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 3);
    EQUAL(r.get("C0"), "あいうえお");
    EQUAL(r.get("C1"), "かきくけこ");
    EQUAL(r.get("C2"), "さしすせそ");
  }

  public void appendNew_4()
  {
    MSG("追加したレコードに対してclearメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    r.clear();
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
  }

  public void appendNew_int()
  {
    MSG("初期カラム容量を指定したレコードの追加。");

    TableEx<String,String> t = new TableEx<String,String>();
    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    for (int i=0; i<10; i++) {
      t.appendNew(10);
      EQUAL(t.recordCount(), i+1);
      EQUAL(t.columnCount(), 0);
    }
  }

  public void appendNew_int_1()
  {
    MSG("引数が負の値の場合。");

    TableEx<String,String> t = new TableEx<String,String>();
    try {
      t.appendNew(-1);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void deleteAll()
  {
    MSG("レコードの全削除。");
    MSG("レコード数が空の場合。");

    TableEx<String,Object> t = new TableEx<String,Object>();
    EQUAL(t.recordCount(), 0);

    t.deleteAll();
    EQUAL(t.recordCount(), 0);
  }

  public void deleteAll_1()
  {
    MSG("レコード数が空でない場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    EQUAL(t.columnCount(), 0);
    EQUAL(t.recordCount(), 1);

    r0.put("c0", "a");
    r0.put("c1", "b");
    r0.put("c2", "c");
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 1);

    Map<String,String> r1 = t.appendNew();
    Map<String,String> r2 = t.appendNew();
    Map<String,String> r3 = t.appendNew();
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 4);

    t.deleteAll();
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 0);
  }

  public void exists_column_value()
  {
    MSG("条件に該当するレコードの存在を確認。");
    MSG("レコード数が1の場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    TRUE(t.exists("c0", "v0"));
    TRUE(t.exists("c1", "v1"));
    TRUE(t.exists("c2", "v2"));

    FALSE(t.exists("c0", "x0"));
    FALSE(t.exists("c1", "x1"));
    FALSE(t.exists("c2", "x2"));
  }

  public void exists_column_value_1()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    FALSE(t.exists("c0", null));
    FALSE(t.exists("c1", null));
    FALSE(t.exists("c2", null));

    FALSE(t.exists(null, "v0"));
    FALSE(t.exists(null, "v1"));
    FALSE(t.exists(null, "v2"));

    FALSE(t.exists(null, null));

    Map<String,String> r1 = t.appendNew();

    TRUE(t.exists("c0", null));
    TRUE(t.exists("c1", null));
    TRUE(t.exists("c2", null));

    FALSE(t.exists(null, "v0"));
    FALSE(t.exists(null, "v1"));
    FALSE(t.exists(null, "v2"));

    FALSE(t.exists(null, null));
  }

  public void exists_column_value_2()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    FALSE(t.exists("c0", "v0"));
    FALSE(t.exists("c1", "v1"));
    FALSE(t.exists("c2", "v2"));

    FALSE(t.exists("c0", "x0"));
    FALSE(t.exists("c1", "x1"));
    FALSE(t.exists("c2", "x2"));

    FALSE(t.exists("c0", null));
    FALSE(t.exists("c1", null));
    FALSE(t.exists("c2", null));

    FALSE(t.exists(null, "v0"));
    FALSE(t.exists(null, "v1"));
    FALSE(t.exists(null, "v2"));

    FALSE(t.exists(null, null));
  }

  public void exists_column_value_3()
  {
    MSG("レコード数が複数の場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v1");
    r2.put("c1", "v4");
    r2.put("c2", "v2");

    TRUE(t.exists("c0", "v0"));
    TRUE(t.exists("c1", "v1"));
    TRUE(t.exists("c2", "v2"));

    FALSE(t.exists("c0", "x"));
    FALSE(t.exists("c1", "y"));
    FALSE(t.exists("c2", "z"));

    FALSE(t.exists("c0", null));
    FALSE(t.exists("c1", null));
    FALSE(t.exists("c2", null));
  }

  public void exists_map()
  {
    MSG("条件に該当するレコードの存在を確認。");
    MSG("レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "v0");
    TRUE(t.exists(c));
    c.put("c1", "v1");
    TRUE(t.exists(c));
    c.put("c2", "v2");
    TRUE(t.exists(c));

    c.clear();

    c.put("c0", "x");
    FALSE(t.exists(c));
    c.put("c0", "v0");
    TRUE(t.exists(c));
    c.put("c1", "y");
    FALSE(t.exists(c));
    c.put("c1", "v1");
    TRUE(t.exists(c));
    c.put("c2", "z");
    FALSE(t.exists(c));

    c.clear();

    c.put("c0", null);
    FALSE(t.exists(c));
    c.put("c0", "v0");
    TRUE(t.exists(c));
    c.put("c1", null);
    FALSE(t.exists(c));
    c.put("c1", "v1");
    TRUE(t.exists(c));
    c.put("c2", null);
    FALSE(t.exists(c));
  }

  public void exists_map_1()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t = new TableEx<String,String>();
    try {
      t.exists(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void exists_map_2()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "v0");
    FALSE(t.exists(c));
    c.put("c1", "v1");
    FALSE(t.exists(c));
    c.put("c2", "v2");
    FALSE(t.exists(c));

    c.clear();

    c.put("c0", "x");
    FALSE(t.exists(c));
    c.put("c0", "v0");
    FALSE(t.exists(c));
    c.put("c1", "y");
    FALSE(t.exists(c));
    c.put("c1", "v1");
    FALSE(t.exists(c));
    c.put("c2", "z");
    FALSE(t.exists(c));

    c.clear();

    c.put("c0", null);
    FALSE(t.exists(c));
    c.put("c0", "v0");
    FALSE(t.exists(c));
    c.put("c1", null);
    FALSE(t.exists(c));
    c.put("c1", "v1");
    FALSE(t.exists(c));
    c.put("c2", null);
    FALSE(t.exists(c));
  }

  public void exists_map_3()
  {
    MSG("レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v4");
    r2.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    TRUE(t.exists(c0));

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c1", "v1");
    TRUE(t.exists(c1));

    Map<String,String> c1x = new HashMap<String,String>();
    c1x.put("c0", "v0");
    c1x.put("c1", "xx");
    FALSE(t.exists(c1x));

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c2", "v2");
    TRUE(t.exists(c2));

    Map<String,String> c2x = new HashMap<String,String>();
    c2x.put("c0", "v0");
    c2x.put("c2", "xx");
    FALSE(t.exists(c2x));

    Map<String,String> c3 = new HashMap<String,String>();
    c3.put("c0", "v0");
    c3.put("c1", "v1");
    c3.put("c2", "v2");
    TRUE(t.exists(c3));

    Map<String,String> c4 = new HashMap<String,String>();
    c4.put("c0", null);
    FALSE(t.exists(c4));

    Map<String,String> c5 = new HashMap<String,String>();
    c5.put("c0", "v0");
    c5.put("c1", null);
    FALSE(t.exists(c5));

    Map<String,String> c6 = new HashMap<String,String>();
    c6.put("c0", "v0");
    c6.put("c1", "v1");
    c6.put("c2", null);
    FALSE(t.exists(c6));
  }

  public void exists_map_4()
  {
    MSG("条件のマップが空の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c = new HashMap<String,String>();
    FALSE(t.exists(c));

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    TRUE(t.exists(c));

    t.deleteAll();

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");
    TRUE(t.exists(c));

    t.deleteAll();

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v4");
    r2.put("c2", "v2");
    TRUE(t.exists(c));
  }

  public void exists_map_5()
  {
    MSG("条件のマップにカラム・キー以外のキーがある場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c2", "v2");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "v0");
    TRUE(t.exists(c));

    c.put("c1", "v1");
    TRUE(t.exists(c));

    c.put("c3", "v3");
    FALSE(t.exists(c));

    c.put("c3", null);
    FALSE(t.exists(c));
  }

  public void selectFirst_column_value()
  {
    MSG("条件に該当する最初のレコードを取得。");
    MSG("レコード数が1で該当レコード数が1の場合。");
    
    TableEx<Integer,String> t = new TableEx<Integer,String>();

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    Map<Integer,String> r0 = t.selectFirst(1, "xxx");
    IDENTIFY(r, r0);

    Map<Integer,String> r1 = t.selectFirst(2, "yyy");
    IDENTIFY(r, r1);

    Map<Integer,String> r2 = t.selectFirst(3, "zzz");
    IDENTIFY(r, r2);
  }

  public void selectFirst_column_value_1()
  {
    MSG("レコード数が1で該当レコード数が0の場合。");

    TableEx<Integer,String> t = new TableEx<Integer,String>();

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    NULL(t.selectFirst(1, "XXX"));

    NULL(t.selectFirst(2, "YYY"));

    NULL(t.selectFirst(3, "ZZZ"));
  }

  public void selectFirst_column_value_2()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();

    Map<String,String> r0 = t.selectFirst(null, null);
    NOTEQUAL(r0, r);

    r.put(null, null);
    Map<String,String> r1 = t.selectFirst(null, null);
    IDENTIFY(r1, r);

    r.put(null, "xxx");
    NULL(t.selectFirst(null, null));
    Map<String,String> r2 = t.selectFirst(null, "xxx");
    IDENTIFY(r2, r);

    r.put("c0", null);
    NULL(t.selectFirst(null, null));
    Map<String,String> r3 = t.selectFirst("c0", null);
    IDENTIFY(r3, r);
  }

  public void selectFirst_column_value_3()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    NULL(t.selectFirst(null, null));

    NULL(t.selectFirst("c0", null));

    NULL(t.selectFirst("c0", "v0"));

    NULL(t.selectFirst(null, "v0"));
  }

  public void selectFirst_column_value_4()
  {
    MSG("レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> rr0 = t.selectFirst("c0", "v0");
    IDENTIFY(rr0, r0);

    Map<String,String> rr1 = t.selectFirst("c1", "v4");
    IDENTIFY(rr1, r1);

    Map<String,String> rr2 = t.selectFirst("c2", "v8");
    IDENTIFY(rr2, r2);
  }

  public void selectFirst_column_value_5()
  {
    MSG("レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r1.put("c0", "v6");
    r1.put("c1", "v7");
    r1.put("c2", "v8");

    NULL(t.selectFirst("c0", "v9"));
    NULL(t.selectFirst("c1", "v8"));
    NULL(t.selectFirst("c2", "v7"));
  }

  public void selectFirst_column_value_6()
  {
    MSG("レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();
    
    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "vx");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "vy");
    r2.put("c2", "v2");

    Map<String,String> rr0 = t.selectFirst("c0", "v0");
    IDENTIFY(rr0, r0);

    Map<String,String> rr1 = t.selectFirst("c1", "v1");
    IDENTIFY(rr1, r0);

    Map<String,String> rr2 = t.selectFirst("c2", "v2");
    IDENTIFY(rr2, r0);
  }

  public void selectFirst_map()
  {
    MSG("条件に該当する最初のレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> r0 = t.selectFirst(c0);
    IDENTIFY(r0, r);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "v2");

    Map<String,String> r1 = t.selectFirst(c1);
    IDENTIFY(r1, r);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "v2");

    Map<String,String> r2 = t.selectFirst(c2);
    IDENTIFY(r2, r);
  }

  public void selectFirst_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "vv");

    NULL(t.selectFirst(c0));

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "xx");

    NULL(t.selectFirst(c1));

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "yy");

    NULL(t.selectFirst(c2));
  }

  public void selectFirst_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t = new TableEx<String,String>();

    try {
      t.selectFirst(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void selectFirst_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    NULL(t.selectFirst(c0));

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c1", null);
    t.deleteAll();
    EQUAL(t.columnCount(), 2);

    NULL(t.selectFirst(c0));
  }

  public void selectFirst_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> rr0 = t.selectFirst(c0);
    IDENTIFY(rr0, r0);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c1", "v4");
    c1.put("c2", "v5");

    Map<String,String> rr1 = t.selectFirst(c1);
    IDENTIFY(rr1, r1);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v6");
    c2.put("c1", "v7");
    c2.put("c2", "v8");

    Map<String,String> rr2 = t.selectFirst(c2);
    IDENTIFY(rr2, r2);
  }

  public void selectFirst_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    NULL(t.selectFirst(c));
  }

  public void selectFirst_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    EQUAL(r0, t.selectFirst(c));

    c.put("c0", "v0");

    EQUAL(r0, t.selectFirst(c));

    c.put("c2", "v3");

    EQUAL(r1, t.selectFirst(c));
  }

  public void selectFirst_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> r0 = t.selectFirst(c);
    EQUAL(r0, r);
  }

  public void selectFirst_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c = new HashMap<String,String>();

    NULL(t.selectFirst(c));
  }

  public void selectFirst_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> r = t.selectFirst(c);
    EQUAL(r0, r);
  }

  public void select_column_value()
  {
    MSG("条件に該当するレコードを取得。");
    MSG("レコード数が1で該当レコード数が1の場合。");

    Table<Integer,String> t = new TableEx<Integer,String>();

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    List<Map<Integer,String>> rL0 = t.select(1, "xxx");
    EQUAL(rL0.size(), 1);
    IDENTIFY(r, rL0.get(0));

    List<Map<Integer,String>> rL1 = t.select(2, "yyy");
    EQUAL(rL1.size(), 1);
    IDENTIFY(r, rL1.get(0));

    List<Map<Integer,String>> rL2 = t.select(3, "zzz");
    EQUAL(rL2.size(), 1);
    IDENTIFY(r, rL2.get(0));
  }

  public void select_column_value_1()
  {
    MSG("レコード数が1で該当レコード数が0の場合。");

    Table<Integer,String> t = new TableEx<Integer,String>();

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    EQUAL(t.select(1, "XXX").size(), 0);

    EQUAL(t.select(2, "YYY").size(), 0);

    EQUAL(t.select(3, "ZZZ").size(), 0);
  }

  public void select_column_value_2()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();

    List<Map<String,String>> rL0 = t.select(null, null);
    EQUAL(rL0.size(), 0);

    r.put(null, null);
    List<Map<String,String>> rL1 = t.select(null, null);
    EQUAL(rL1.size(), 1); 
    IDENTIFY(rL1.get(0), r);

    r.put(null, "xxx");
    EQUAL(t.select(null, null).size(), 0);
    List<Map<String,String>> rL2 = t.select(null, "xxx");
    IDENTIFY(rL2.get(0), r);

    r.put("c0", null);
    EQUAL(t.select(null, null).size(), 0);
    List<Map<String,String>> rL3 = t.select("c0", null);
    IDENTIFY(rL3.get(0), r);
  }

  public void select_column_value_3()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    EQUAL(t.select(null, null).size(), 0);

    EQUAL(t.select("c0", null).size(), 0);

    EQUAL(t.select("c0", "v0").size(), 0);

    EQUAL(t.select(null, "v0").size(), 0);
  }

  public void select_column_value_4()
  {
    MSG("レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    List<Map<String,String>> rL0 = t.select("c0", "v0");
    EQUAL(rL0.size(), 1);
    IDENTIFY(rL0.get(0), r0);

    List<Map<String,String>> rL1 = t.select("c1", "v4");
    EQUAL(rL1.size(), 1);
    IDENTIFY(rL1.get(0), r1);

    List<Map<String,String>> rL2 = t.select("c2", "v8");
    EQUAL(rL2.size(), 1);
    IDENTIFY(rL2.get(0), r2);
  }

  public void select_column_value_5()
  {
    MSG("レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r1.put("c0", "v6");
    r1.put("c1", "v7");
    r1.put("c2", "v8");

    EQUAL(t.select("c0", "v9").size(), 0);
    EQUAL(t.select("c1", "v8").size(), 0);
    EQUAL(t.select("c2", "v7").size(), 0);
  }

  public void select_column_value_6()
  {
    MSG("レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();
    
    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "vx");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "vy");
    r2.put("c2", "v2");

    List<Map<String,String>> rrL0 = t.select("c0", "v0");
    EQUAL(rrL0.size(), 3);
    IDENTIFY(rrL0.get(0), r0);
    IDENTIFY(rrL0.get(1), r1);
    IDENTIFY(rrL0.get(2), r2);

    List<Map<String,String>> rrL1 = t.select("c1", "v1");
    EQUAL(rrL1.size(), 2);
    IDENTIFY(rrL1.get(0), r0);
    IDENTIFY(rrL1.get(1), r1);

    List<Map<String,String>> rrL2 = t.select("c2", "v2");
    EQUAL(rrL2.size(), 2);
    IDENTIFY(rrL2.get(0), r0);
    IDENTIFY(rrL2.get(1), r2);
  }

  public void select_map()
  {
    MSG("条件に該当するレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    List<Map<String,String>> rL0 = t.select(c0);
    EQUAL(rL0.size(), 1);
    IDENTIFY(rL0.get(0), r);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "v2");

    List<Map<String,String>> rL1 = t.select(c1);
    EQUAL(rL1.size(), 1);
    IDENTIFY(rL1.get(0), r);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "v2");

    List<Map<String,String>> rL2 = t.select(c2);
    EQUAL(rL2.size(), 1);
    IDENTIFY(rL2.get(0), r);
  }

  public void select_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "vv");

    List<Map<String,String>> rL0 = t.select(c0);
    EQUAL(rL0.size(), 0);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "xx");

    List<Map<String,String>> rL1 = t.select(c1);
    EQUAL(rL1.size(), 0);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "yy");

    List<Map<String,String>> rL2 = t.select(c2);
    EQUAL(rL2.size(), 0);
  }

  public void select_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t = new TableEx<String,String>();

    try {
      t.select(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void select_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    EQUAL(t.select(c0).size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c1", null);
    t.deleteAll();
    EQUAL(t.columnCount(), 2);

    EQUAL(t.select(c0).size(), 0);
  }

  public void select_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    List<Map<String,String>> rrL0 = t.select(c0);
    EQUAL(rrL0.size(), 1);
    IDENTIFY(rrL0.get(0), r0);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c1", "v4");
    c1.put("c2", "v5");

    List<Map<String,String>> rrL1 = t.select(c1);
    EQUAL(rrL1.size(), 1);
    IDENTIFY(rrL1.get(0), r1);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v6");
    c2.put("c1", "v7");
    c2.put("c2", "v8");

    List<Map<String,String>> rrL2 = t.select(c2);
    EQUAL(rrL2.size(), 1);
    IDENTIFY(rrL2.get(0), r2);
  }

  public void select_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    EQUAL(t.select(c).size(), 0);
  }

  public void select_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL0 = t.select(c);
    EQUAL(rL0.size(), 3);
    IDENTIFY(rL0.get(0), r0);
    IDENTIFY(rL0.get(1), r1);
    IDENTIFY(rL0.get(2), r2);

    c.put("c0", "v0");

    List<Map<String,String>> rL1 = t.select(c);
    EQUAL(rL1.size(), 3);
    IDENTIFY(rL1.get(0), r0);
    IDENTIFY(rL1.get(1), r1);
    IDENTIFY(rL1.get(2), r2);

    c.put("c2", "v3");

    List<Map<String,String>> rL2 = t.select(c);
    EQUAL(rL2.size(), 2);
    IDENTIFY(rL2.get(0), r1);
    IDENTIFY(rL2.get(1), r2);
  }

  public void select_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL0 = t.select(c);
    EQUAL(rL0.size(), 1);
    EQUAL(rL0.get(0), r);
  }

  public void select_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c = new HashMap<String,String>();

    EQUAL(t.select(c).size(), 0);
  }

  public void select_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL = t.select(c);
    EQUAL(rL.size(), 3);
    EQUAL(rL.get(0), r0);
    EQUAL(rL.get(1), r1);
    EQUAL(rL.get(2), r2);
  }

  public void delete_map()
  {
    MSG("条件に該当するレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    for (int i=0; i<3; i++) {
      TableEx<String,String> t = new TableEx<String,String>();
  
      Map<String,String> r = t.appendNew();
      r.put("c0", "v0");
      r.put("c1", "v1");
      r.put("c2", "v2");

      switch (i) {
      case 0 : {
          Map<String,String> c0 = new HashMap<String,String>();
          c0.put("c0", "v0");
          c0.put("c1", "v1");
      
          List<Map<String,String>> rL0 = t.delete(c0);
          EQUAL(rL0.size(), 1);
          IDENTIFY(rL0.get(0), r);
          EQUAL(t.recordCount(), 0);
        } break;

      case 1 : {
          Map<String,String> c1 = new HashMap<String,String>();
          c1.put("c0", "v0");
          c1.put("c2", "v2");
  
          List<Map<String,String>> rL1 = t.delete(c1);
          EQUAL(rL1.size(), 1);
          IDENTIFY(rL1.get(0), r);
          EQUAL(t.recordCount(), 0);
        } break;

      case 2 : {
          Map<String,String> c2 = new HashMap<String,String>();
          c2.put("c0", "v0");
          c2.put("c1", "v1");
          c2.put("c2", "v2");
    
          List<Map<String,String>> rL2 = t.delete(c2);
          EQUAL(rL2.size(), 1);
          IDENTIFY(rL2.get(0), r);
          EQUAL(t.recordCount(), 0);
        } break;
      }
    }
  }

  public void delete_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    for (int i=0; i<3; i++) {
      TableEx<String,String> t = new TableEx<String,String>();

      Map<String,String> r = t.appendNew();
      r.put("c0", "v0");
      r.put("c1", "v1");
      r.put("c2", "v2");

      switch (i) {
      case 0 : {
          Map<String,String> c0 = new HashMap<String,String>();
          c0.put("c0", "v0");
          c0.put("c1", "vv");
  
          List<Map<String,String>> rL0 = t.delete(c0);
          EQUAL(rL0.size(), 0);
          EQUAL(t.recordCount(), 1);
        } break;

      case 1 : {
          Map<String,String> c1 = new HashMap<String,String>();
          c1.put("c0", "v0");
          c1.put("c2", "xx");

          List<Map<String,String>> rL1 = t.delete(c1);
          EQUAL(rL1.size(), 0);
          EQUAL(t.recordCount(), 1);
        } break;

      case 2 : {
          Map<String,String> c2 = new HashMap<String,String>();
          c2.put("c0", "v0");
          c2.put("c1", "v1");
          c2.put("c2", "yy");

          List<Map<String,String>> rL2 = t.delete(c2);
          EQUAL(rL2.size(), 0);
          EQUAL(t.recordCount(), 1);
        } break;
      }
    }
  }

  public void delete_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t = new TableEx<String,String>();

    try {
      t.select(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void delete_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    EQUAL(t.delete(c0).size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c0", null);
    t.deleteAll();
  }

  public void delete_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    for (int i=0; i<3; i++) { 
      Table<String,String> t = new TableEx<String,String>();
  
      Map<String,String> r0 = t.appendNew();
      r0.put("c0", "v0");
      r0.put("c1", "v1");
      r0.put("c2", "v2");
  
      Map<String,String> r1 = t.appendNew();
      r1.put("c0", "v3");
      r1.put("c1", "v4");
      r1.put("c2", "v5");
  
      Map<String,String> r2 = t.appendNew();
      r2.put("c0", "v6");
      r2.put("c1", "v7");
      r2.put("c2", "v8");
  
      switch (i) {
      case 0: {
        Map<String,String> c0 = new HashMap<String,String>();
        c0.put("c0", "v0");
        c0.put("c1", "v1");
  
        List<Map<String,String>> rL0 = t.delete(c0);
        EQUAL(rL0.size(), 1);
        IDENTIFY(rL0.get(0), r0);
        EQUAL(t.recordCount(), 2);
        List<Map<String,String>> rL00 = t.select(new HashMap<String,String>());
        EQUAL(rL00.get(0), r1);
        EQUAL(rL00.get(1), r2);
        } break;

      case 1: {
        Map<String,String> c1 = new HashMap<String,String>();
        c1.put("c1", "v4");
        c1.put("c2", "v5");
  
        List<Map<String,String>> rL1 = t.delete(c1);
        EQUAL(rL1.size(), 1);
        IDENTIFY(rL1.get(0), r1);
        EQUAL(t.recordCount(), 2);
        List<Map<String,String>> rL11 = t.select(new HashMap<String,String>());
        EQUAL(rL11.get(0), r0);
        EQUAL(rL11.get(1), r2);
        } break;

      case 2: {
        Map<String,String> c2 = new HashMap<String,String>();
        c2.put("c2", "v6");
        c2.put("c2", "v7");
        c2.put("c2", "v8");

        List<Map<String,String>> rL2 = t.delete(c2);
        EQUAL(rL2.size(), 1);
        IDENTIFY(rL2.get(0), r2);
        EQUAL(t.recordCount(), 2);
        List<Map<String,String>> rL22 = t.select(new HashMap<String,String>());
        EQUAL(rL22.get(0), r0);
        EQUAL(rL22.get(1), r1);
        } break;
      }
    }  
  }

  public void delete_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    EQUAL(t.delete(c).size(), 0);
    EQUAL(t.recordCount(), 3);
  }

  public void delete_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    for (int i=0; i<3; i++) {
      Table<String,String> t = new TableEx<String,String>();
  
      Map<String,String> r0 = t.appendNew();
      r0.put("c0", "v0");
      r0.put("c1", "v1");
      r0.put("c2", "v2");
  
      Map<String,String> r1 = t.appendNew();
      r1.put("c0", "v0");
      r1.put("c1", "vx");
      r1.put("c2", "v3");
  
      Map<String,String> r2 = t.appendNew();
      r2.put("c0", "v0");
      r2.put("c1", "v1");
      r2.put("c2", "v3");

      switch (i) {
      case 0: {
        Map<String,String> c = new HashMap<String,String>();

        List<Map<String,String>> rL0 = t.delete(c);
        EQUAL(rL0.size(), 3);
        IDENTIFY(rL0.get(0), r0);
        IDENTIFY(rL0.get(1), r1);
        IDENTIFY(rL0.get(2), r2);
        EQUAL(t.recordCount(), 0);
        } break;
      case 1: {
        Map<String,String> c = new HashMap<String,String>();
        c.put("c0", "v0");
    
        List<Map<String,String>> rL1 = t.delete(c);
        EQUAL(rL1.size(), 3);
        IDENTIFY(rL1.get(0), r0);
        IDENTIFY(rL1.get(1), r1);
        IDENTIFY(rL1.get(2), r2);
        EQUAL(t.recordCount(), 0);
        } break;
      case 2: {
        Map<String,String> c = new HashMap<String,String>();
        c.put("c2", "v3");
    
        List<Map<String,String>> rL2 = t.delete(c);
        EQUAL(rL2.size(), 2);
        IDENTIFY(rL2.get(0), r1);
        IDENTIFY(rL2.get(1), r2);
        EQUAL(t.recordCount(), 1);
        List<Map<String,String>> rL22 = t.select(new HashMap<String,String>());
        EQUAL(rL22.get(0), r0);
        } break;
      }
    }
  }

  public void delete_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL0 = t.delete(c);
    EQUAL(rL0.size(), 1);
    EQUAL(rL0.get(0), r);
    EQUAL(t.recordCount(), 0);
  }

  public void delete_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c = new HashMap<String,String>();

    EQUAL(t.delete(c).size(), 0);
  }

  public void delete_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL = t.delete(c);
    EQUAL(rL.size(), 3);
    EQUAL(rL.get(0), r0);
    EQUAL(rL.get(1), r1);
    EQUAL(rL.get(2), r2);
    EQUAL(t.recordCount(), 0);
  }

  public void update_map()
  {
    MSG("条件に該当するレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");
    r.put("c3", "v3");
    r.put("c4", "v4");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c3", "yIII");
    d0.put("c4", "yIV");

    List<Map<String,String>> rL0 = t.update(c0, d0);
    EQUAL(rL0.size(), 1);
    IDENTIFY(rL0.get(0), r);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "yIII");
    EQUAL(r.get("c4"), "yIV");

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "v2");

    Map<String,String> d1 = new HashMap<String,String>();
    d1.put("c3", "あ");
    d1.put("c4", "い");

    List<Map<String,String>> rL1 = t.update(c1, d1);
    EQUAL(rL1.size(), 1);
    IDENTIFY(rL1.get(0), r);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "あ");
    EQUAL(r.get("c4"), "い");

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "v2");

    Map<String,String> d2 = new HashMap<String,String>();
    d2.put("c3", "a");
    d2.put("c4", "i");

    List<Map<String,String>> rL2 = t.update(c2, d2);
    EQUAL(rL2.size(), 1);
    IDENTIFY(rL2.get(0), r);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "a");
    EQUAL(r.get("c4"), "i");
  }

  public void update_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");
    r.put("c3", "v3");
    r.put("c4", "v4");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "vv");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c3", "XX");
    d0.put("c4", "YY");

    List<Map<String,String>> rL0 = t.update(c0, d0);
    EQUAL(rL0.size(), 0);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "v3");
    EQUAL(r.get("c4"), "v4");

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "xx");

    Map<String,String> d1 = new HashMap<String,String>();
    d1.put("c3", "XX");
    d1.put("c4", "YY");

    List<Map<String,String>> rL1 = t.update(c1, d1);
    EQUAL(rL1.size(), 0);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "v3");
    EQUAL(r.get("c4"), "v4");

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "yy");

    Map<String,String> d2 = new HashMap<String,String>();
    d2.put("c3", "XX");
    d2.put("c4", "YY");

    List<Map<String,String>> rL2 = t.update(c2, d2);
    EQUAL(rL2.size(), 0);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "v3");
    EQUAL(r.get("c4"), "v4");
  }

  public void update_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();

    try {
      t.update(null, d);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }

    try {
      t.update(c, null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void update_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c0", "V0");
    d0.put("c1", "V1");

    EQUAL(t.update(c0, d0).size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c1", null);
    t.deleteAll();
    EQUAL(t.columnCount(), 2);

    EQUAL(t.update(c0, d0).size(), 0);
  }

  public void update_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "V3");
    r0.put("c4", "V4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");
    r1.put("c3", "V3");
    r1.put("c4", "V4");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");
    r2.put("c3", "V3");
    r2.put("c4", "V4");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c3", "VV3");
    d0.put("c4", "VV4");

    List<Map<String,String>> rrL0 = t.update(c0, d0);
    EQUAL(rrL0.size(), 1);
    IDENTIFY(rrL0.get(0), r0);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "VV3");
    EQUAL(r0.get("c4"), "VV4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r1.get("c3"), "V3");
    EQUAL(r1.get("c4"), "V4");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
    EQUAL(r2.get("c3"), "V3");
    EQUAL(r2.get("c4"), "V4");

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c1", "v4");
    c1.put("c2", "v5");

    Map<String,String> d1 = new HashMap<String,String>();
    d1.put("c3", "XXXXXX");
    d1.put("c4", "YYYYYY");

    List<Map<String,String>> rrL1 = t.update(c1, d1);
    EQUAL(rrL1.size(), 1);
    IDENTIFY(rrL1.get(0), r1);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "VV3");
    EQUAL(r0.get("c4"), "VV4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r1.get("c3"), "XXXXXX");
    EQUAL(r1.get("c4"), "YYYYYY");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
    EQUAL(r2.get("c3"), "V3");
    EQUAL(r2.get("c4"), "V4");

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v6");
    c2.put("c1", "v7");
    c2.put("c2", "v8");

    Map<String,String> d2 = new HashMap<String,String>();
    d2.put("c3", "あいうえお");
    d2.put("c4", "かきくけこ");

    List<Map<String,String>> rrL2 = t.update(c2, d2);
    EQUAL(rrL2.size(), 1);
    IDENTIFY(rrL2.get(0), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "VV3");
    EQUAL(r0.get("c4"), "VV4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r1.get("c3"), "XXXXXX");
    EQUAL(r1.get("c4"), "YYYYYY");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
    EQUAL(r2.get("c3"), "あいうえお");
    EQUAL(r2.get("c4"), "かきくけこ");
  }

  public void update_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "v3");
    r0.put("c4", "v4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    Map<String,String> d = new HashMap<String,String>();
    c.put("c3", "d0");
    c.put("c4", "d1");

    EQUAL(t.update(c, d).size(), 0);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "v3");
    EQUAL(r0.get("c4"), "v4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
  }

  public void update_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "v3");
    r0.put("c4", "v4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    List<Map<String,String>> rL0 = t.update(c, d);
    EQUAL(rL0.size(), 3);
    IDENTIFY(rL0.get(0), r0);
    IDENTIFY(rL0.get(1), r1);
    IDENTIFY(rL0.get(2), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "XX");
    EQUAL(r0.get("c4"), "YY");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "XX");
    EQUAL(r1.get("c4"), "YY");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "XX");
    EQUAL(r2.get("c4"), "YY");

    c.put("c0", "v0");
    d.put("c3", "あいうえお");
    d.put("c4", "かきくけこ");

    List<Map<String,String>> rL1 = t.update(c, d);
    EQUAL(rL1.size(), 3);
    IDENTIFY(rL1.get(0), r0);
    IDENTIFY(rL1.get(1), r1);
    IDENTIFY(rL1.get(2), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "あいうえお");
    EQUAL(r0.get("c4"), "かきくけこ");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "あいうえお");
    EQUAL(r1.get("c4"), "かきくけこ");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "あいうえお");
    EQUAL(r2.get("c4"), "かきくけこ");

    c.put("c2", "v3");
    d.put("c3", "ABCDEFG");
    d.put("c4", "HIJKLMN");

    List<Map<String,String>> rL2 = t.update(c, d);
    EQUAL(rL2.size(), 2);
    IDENTIFY(rL2.get(0), r1);
    IDENTIFY(rL2.get(1), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "あいうえお");
    EQUAL(r0.get("c4"), "かきくけこ");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "ABCDEFG");
    EQUAL(r1.get("c4"), "HIJKLMN");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "ABCDEFG");
    EQUAL(r2.get("c4"), "HIJKLMN");
  }

  public void update_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    List<Map<String,String>> rL0 = t.update(c, d);
    EQUAL(rL0.size(), 1);
    EQUAL(rL0.get(0), r);

    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c3"), "XX");
    EQUAL(r.get("c4"), "YY");
  }

  public void update_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    EQUAL(t.update(c, d).size(), 0);
  }

  public void update_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t = new TableEx<String,String>();

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "v3");
    r0.put("c4", "v4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    List<Map<String,String>> rL = t.update(c, d);
    EQUAL(rL.size(), 3);
    EQUAL(rL.get(0), r0);
    EQUAL(rL.get(1), r1);
    EQUAL(rL.get(2), r2);

    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "XX");
    EQUAL(r0.get("c4"), "YY");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "XX");
    EQUAL(r1.get("c4"), "YY");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "XX");
    EQUAL(r2.get("c4"), "YY");
  }

  public void getIndex()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t0= new TableEx<String,String>();
    try {
      Index<String,String> t = t0.getIndex((String[])null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void getIndex_1()
  {
    MSG("引数の配列のサイズが0の場合。");

    TableEx<String,String> t0= new TableEx<String,String>();
    try {
      Index<String,String> t = t0.getIndex(new String[0]);
      NG();
    } catch (IllegalArgumentException e) {
      OK(e);
    }
  }

  public void getIndex_and_appendNew()
  {
    MSG("インデックスを作成して、レコードを追加。");
    MSG("空のテーブルにレコードを追加。");

    TableEx<String,String> t0= new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    for (int i=0; i<10; i++) {
      t.appendNew();
      EQUAL(t.recordCount(), i+1);
      EQUAL(t.columnCount(), 0);
    }
  }

  public void getIndex_and_appendNew_1()
  {
    MSG("空でないテーブルにレコードを追加。");

    TableEx<String,String> t = new TableEx<String,String>();

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    Map<String,String> r1 = t.appendNew();
    Map<String,String> r2 = t.appendNew();
    EQUAL(r.size(), 2);
    EQUAL(r1.size(), 2);
    EQUAL(r2.size(), 2);
    EQUAL(t.recordCount(), 3);
    EQUAL(t.columnCount(), 2);

    Index<String,String> t1 = t.getIndex("C0", "C1");
    EQUAL(t1.recordCount(), 3);
    EQUAL(t1.columnCount(), 2);
    Enumeration<String> e = t1.columns();
    TRUE(e.hasMoreElements());
    EQUAL(e.nextElement(), "C0");
    TRUE(e.hasMoreElements());
    EQUAL(e.nextElement(), "C1");
    FALSE(e.hasMoreElements());
    MapIterator<String,String> i = t1.records();
    TRUE(i.hasNext());
    EQUAL(i.next(), r);
    TRUE(i.hasNext());
    EQUAL(i.next(), r1);
    TRUE(i.hasNext());
    EQUAL(i.next(), r2);
    FALSE(i.hasNext());
  }

  public void getIndex_and_appendNew_2()
  {
    MSG("追加したレコードに対してputメソッドを実行。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("C0");

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    Set<String> s = new HashSet<String>();
    s.add("C0");
    s.add("C1");
    EQUAL(s, r.keySet());

    Set<String> s1 = new HashSet<String>();
    Enumeration<String> e1 = t.columns();
    while (e1.hasMoreElements()) {
      s1.add(e1.nextElement());
    }
    EQUAL(s, s1);
  }

  public void getIndex_and_appendNew_3()
  {
    MSG("追加したレコードに対してremoveメソッドを実行。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("C0");
    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    EQUAL(r.remove("C0"), "V0");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(r.get("C0"), null);
  }

  public void getIndex_and_appendNew_4()
  {
    MSG("追加したレコードに対してputAllメソッドを実行。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    Map<String,String> m = new HashMap<String,String>();
    m.put("C0", "あいうえお");
    m.put("C1", "かきくけこ");
    m.put("C2", "さしすせそ");

    r.putAll(m);
    EQUAL(r.size(), 3);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 3);
    EQUAL(r.get("C0"), "あいうえお");
    EQUAL(r.get("C1"), "かきくけこ");
    EQUAL(r.get("C2"), "さしすせそ");
  }

  public void getIndex_and_appendNew_5()
  {
    MSG("追加したレコードに対してclearメソッドを実行。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);

    r.clear();
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
  }

  public void getIndex_and_appendNew_int()
  {
    MSG("初期カラム容量を指定したレコードの追加。");

    TableEx<String,String> t0= new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);

    for (int i=0; i<10; i++) {
      t.appendNew(10);
      EQUAL(t.recordCount(), i+1);
      EQUAL(t.columnCount(), 0);
    }
  }

  public void getIndex_and_appendNew_int_1()
  {
    MSG("引数が負の値の場合。");
    TableEx<String,String> t0= new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");
    try {
      t.appendNew(-1);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void getIndex_and_deleteAll()
  {
    MSG("レコードの全削除。");
    MSG("レコード数が空の場合。");

    TableEx<String,Object> t0 = new TableEx<String,Object>();
    Index<String,Object> t = t0.getIndex("c0");
    EQUAL(t.recordCount(), 0);

    t.deleteAll();
    EQUAL(t.recordCount(), 0);
  }

  public void getIndex_and_deleteAll_1()
  {
    MSG("レコード数が空でない場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    Map<String,String> r0 = t.appendNew();
    EQUAL(t.columnCount(), 0);
    EQUAL(t.recordCount(), 1);

    r0.put("c0", "a");
    r0.put("c1", "b");
    r0.put("c2", "c");
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 1);

    Map<String,String> r1 = t.appendNew();
    Map<String,String> r2 = t.appendNew();
    Map<String,String> r3 = t.appendNew();
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 4);

    t.deleteAll();
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 0);
  }

  public void getIndex_and_exists_column_value()
  {
    MSG("インデックスを作成して、条件に該当するレコードの存在を確認。");
    MSG("レコード数が1の場合。");

    TableEx<String,String> t0= new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    TRUE(t.exists("c0", "v0"));
    TRUE(t.exists("c1", "v1"));
    TRUE(t.exists("c2", "v2"));

    FALSE(t.exists("c0", "x0"));
    FALSE(t.exists("c1", "x1"));
    FALSE(t.exists("c2", "x2"));
  }

  public void getIndex_and_exists_column_value_1()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t0= new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    FALSE(t.exists("c0", null));
    FALSE(t.exists("c1", null));
    FALSE(t.exists("c2", null));

    FALSE(t.exists(null, "v0"));
    FALSE(t.exists(null, "v1"));
    FALSE(t.exists(null, "v2"));

    FALSE(t.exists(null, null));

    Map<String,String> r1 = t.appendNew();

    TRUE(t.exists("c0", null));
    TRUE(t.exists("c1", null));
    TRUE(t.exists("c2", null));

    FALSE(t.exists(null, "v0"));
    FALSE(t.exists(null, "v1"));
    FALSE(t.exists(null, "v2"));

    FALSE(t.exists(null, null));
  }

  public void getIndex_and_exists_column_value_2()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    FALSE(t.exists("c0", "v0"));
    FALSE(t.exists("c1", "v1"));
    FALSE(t.exists("c2", "v2"));

    FALSE(t.exists("c0", "x0"));
    FALSE(t.exists("c1", "x1"));
    FALSE(t.exists("c2", "x2"));

    FALSE(t.exists("c0", null));
    FALSE(t.exists("c1", null));
    FALSE(t.exists("c2", null));

    FALSE(t.exists(null, "v0"));
    FALSE(t.exists(null, "v1"));
    FALSE(t.exists(null, "v2"));

    FALSE(t.exists(null, null));
  }

  public void getIndex_and_exists_column_value_3()
  {
    MSG("レコード数が複数の場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v1");
    r2.put("c1", "v4");
    r2.put("c2", "v2");

    TRUE(t.exists("c0", "v0"));
    TRUE(t.exists("c1", "v1"));
    TRUE(t.exists("c2", "v2"));

    FALSE(t.exists("c0", "x"));
    FALSE(t.exists("c1", "y"));
    FALSE(t.exists("c2", "z"));

    FALSE(t.exists("c0", null));
    FALSE(t.exists("c1", null));
    FALSE(t.exists("c2", null));
  }

  public void getIndex_and_exists_map()
  {
    MSG("インデックスを作成して、条件に該当するレコードの存在を確認。");
    MSG("レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "v0");
    TRUE(t.exists(c));
    c.put("c1", "v1");
    TRUE(t.exists(c));
    c.put("c2", "v2");
    TRUE(t.exists(c));

    c.clear();

    c.put("c0", "x");
    FALSE(t.exists(c));
    c.put("c0", "v0");
    TRUE(t.exists(c));
    c.put("c1", "y");
    FALSE(t.exists(c));
    c.put("c1", "v1");
    TRUE(t.exists(c));
    c.put("c2", "z");
    FALSE(t.exists(c));

    c.clear();

    c.put("c0", null);
    FALSE(t.exists(c));
    c.put("c0", "v0");
    TRUE(t.exists(c));
    c.put("c1", null);
    FALSE(t.exists(c));
    c.put("c1", "v1");
    TRUE(t.exists(c));
    c.put("c2", null);
    FALSE(t.exists(c));
  }

  public void getIndex_and_exists_map_1()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");
    try {
      t.exists(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void getIndex_and_exists_map_2()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0","c1");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "v0");
    FALSE(t.exists(c));
    c.put("c1", "v1");
    FALSE(t.exists(c));
    c.put("c2", "v2");
    FALSE(t.exists(c));

    c.clear();

    c.put("c0", "x");
    FALSE(t.exists(c));
    c.put("c0", "v0");
    FALSE(t.exists(c));
    c.put("c1", "y");
    FALSE(t.exists(c));
    c.put("c1", "v1");
    FALSE(t.exists(c));
    c.put("c2", "z");
    FALSE(t.exists(c));

    c.clear();

    c.put("c0", null);
    FALSE(t.exists(c));
    c.put("c0", "v0");
    FALSE(t.exists(c));
    c.put("c1", null);
    FALSE(t.exists(c));
    c.put("c1", "v1");
    FALSE(t.exists(c));
    c.put("c2", null);
    FALSE(t.exists(c));
  }

  public void getIndex_and_exists_map_3()
  {
    MSG("レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v4");
    r2.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    TRUE(t.exists(c0));

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c1", "v1");
    TRUE(t.exists(c1));

    Map<String,String> c1x = new HashMap<String,String>();
    c1x.put("c0", "v0");
    c1x.put("c1", "xx");
    FALSE(t.exists(c1x));

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c2", "v2");
    TRUE(t.exists(c2));

    Map<String,String> c2x = new HashMap<String,String>();
    c2x.put("c0", "v0");
    c2x.put("c2", "xx");
    FALSE(t.exists(c2x));

    Map<String,String> c3 = new HashMap<String,String>();
    c3.put("c0", "v0");
    c3.put("c1", "v1");
    c3.put("c2", "v2");
    TRUE(t.exists(c3));

    Map<String,String> c4 = new HashMap<String,String>();
    c4.put("c0", null);
    FALSE(t.exists(c4));

    Map<String,String> c5 = new HashMap<String,String>();
    c5.put("c0", "v0");
    c5.put("c1", null);
    FALSE(t.exists(c5));

    Map<String,String> c6 = new HashMap<String,String>();
    c6.put("c0", "v0");
    c6.put("c1", "v1");
    c6.put("c2", null);
    FALSE(t.exists(c6));
  }

  public void getIndex_and_exists_map_4()
  {
    MSG("条件のマップが空の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> c = new HashMap<String,String>();
    FALSE(t.exists(c));

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    TRUE(t.exists(c));

    t.deleteAll();

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");
    TRUE(t.exists(c));

    t.deleteAll();

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v4");
    r2.put("c2", "v2");
    TRUE(t.exists(c));
  }

  public void getIndex_and_exists_map_5()
  {
    MSG("条件のマップにカラム・キー以外のキーがある場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c2", "v2");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "v0");
    TRUE(t.exists(c));

    c.put("c1", "v1");
    TRUE(t.exists(c));

    c.put("c3", "v3");
    FALSE(t.exists(c));

    c.put("c3", null);
    FALSE(t.exists(c));
  }

  public void getIndex_and_selectFirst_column_value()
  {
    MSG("インデックスを作成して、条件に該当する最初のレコードを取得。");
    MSG("レコード数が1で該当レコード数が1の場合。");
    
    TableEx<Integer,String> t0 = new TableEx<Integer,String>();
    Index<Integer,String> t = t0.getIndex(1, 2);

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    Map<Integer,String> r0 = t.selectFirst(1, "xxx");
    IDENTIFY(r, r0);

    Map<Integer,String> r1 = t.selectFirst(2, "yyy");
    IDENTIFY(r, r1);

    Map<Integer,String> r2 = t.selectFirst(3, "zzz");
    IDENTIFY(r, r2);
  }

  public void getIndex_and_selectFirst_column_value_1()
  {
    MSG("レコード数が1で該当レコード数が0の場合。");

    TableEx<Integer,String> t0 = new TableEx<Integer,String>();
    Index<Integer,String> t = t0.getIndex(1, 2);

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    NULL(t.selectFirst(1, "XXX"));

    NULL(t.selectFirst(2, "YYY"));

    NULL(t.selectFirst(3, "ZZZ"));
  }

  public void getIndex_and_selectFirst_column_value_2()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c1");

    Map<String,String> r = t.appendNew();

    Map<String,String> r0 = t.selectFirst(null, null);
    NOTEQUAL(r0, r);

    r.put(null, null);
    Map<String,String> r1 = t.selectFirst(null, null);
    IDENTIFY(r1, r);

    r.put(null, "xxx");
    NULL(t.selectFirst(null, null));
    Map<String,String> r2 = t.selectFirst(null, "xxx");
    IDENTIFY(r2, r);

    r.put("c0", null);
    NULL(t.selectFirst(null, null));
    Map<String,String> r3 = t.selectFirst("c0", null);
    IDENTIFY(r3, r);
  }

  public void getIndex_and_selectFirst_column_value_3()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    NULL(t.selectFirst(null, null));

    NULL(t.selectFirst("c0", null));

    NULL(t.selectFirst("c0", "v0"));

    NULL(t.selectFirst(null, "v0"));
  }

  public void getIndex_and_selectFirst_column_value_4()
  {
    MSG("レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> rr0 = t.selectFirst("c0", "v0");
    IDENTIFY(rr0, r0);

    Map<String,String> rr1 = t.selectFirst("c1", "v4");
    IDENTIFY(rr1, r1);

    Map<String,String> rr2 = t.selectFirst("c2", "v8");
    IDENTIFY(rr2, r2);
  }

  public void getIndex_and_selectFirst_column_value_5()
  {
    MSG("レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Table<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r1.put("c0", "v6");
    r1.put("c1", "v7");
    r1.put("c2", "v8");

    NULL(t.selectFirst("c0", "v9"));
    NULL(t.selectFirst("c1", "v8"));
    NULL(t.selectFirst("c2", "v7"));
  }

  public void getIndex_and_selectFirst_column_value_6()
  {
    MSG("レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");
    
    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "vx");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "vy");
    r2.put("c2", "v2");

    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();

    Map<String,String> rr0 = t.selectFirst("c0", "v0");
    set.add(r0);
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(rr0));

    Map<String,String> rr1 = t.selectFirst("c1", "v1");
    set.add(r0);
    set.add(r1);
    TRUE(set.contains(rr1));

    Map<String,String> rr2 = t.selectFirst("c2", "v2");
    set.add(r0);
    set.add(r2);
    TRUE(set.contains(rr2));
  }

  public void getIndex_and_selectFirst_map()
  {
    MSG("インデックスを作成して、条件に該当する最初のレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> r0 = t.selectFirst(c0);
    IDENTIFY(r0, r);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "v2");

    Map<String,String> r1 = t.selectFirst(c1);
    IDENTIFY(r1, r);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "v2");

    Map<String,String> r2 = t.selectFirst(c2);
    IDENTIFY(r2, r);
  }

  public void getIndex_and_selectFirst_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "vv");

    NULL(t.selectFirst(c0));

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "xx");

    NULL(t.selectFirst(c1));

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "yy");

    NULL(t.selectFirst(c2));
  }

  public void getIndex_and_selectFirst_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    try {
      t.selectFirst(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void getIndex_and_selectFirst_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    NULL(t.selectFirst(c0));

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c1", null);
    t.deleteAll();
    EQUAL(t.columnCount(), 2);

    NULL(t.selectFirst(c0));
  }

  public void getIndex_and_selectFirst_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> rr0 = t.selectFirst(c0);
    IDENTIFY(rr0, r0);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c1", "v4");
    c1.put("c2", "v5");

    Map<String,String> rr1 = t.selectFirst(c1);
    IDENTIFY(rr1, r1);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v6");
    c2.put("c1", "v7");
    c2.put("c2", "v8");

    Map<String,String> rr2 = t.selectFirst(c2);
    IDENTIFY(rr2, r2);
  }

  public void getIndex_and_selectFirst_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    NULL(t.selectFirst(c));
  }

  public void getIndex_and_selectFirst_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();
    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();
    set.add(r0);
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(t.selectFirst(c)));

    c.put("c0", "v0");
    set.clear();
    set.add(r0);
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(t.selectFirst(c)));

    c.put("c2", "v3");
    set.clear();
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(t.selectFirst(c)));
  }

  public void getIndex_and_selectFirst_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> r0 = t.selectFirst(c);
    EQUAL(r0, r);
  }

  public void getIndex_and_selectFirst_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    Map<String,String> c = new HashMap<String,String>();

    NULL(t.selectFirst(c));
  }

  public void getIndex_and_selectFirst_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();
    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();
    set.add(r0);
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(t.selectFirst(c)));
  }

  public void getIndex_and_select_column_value()
  {
    MSG("インデックスを作成して、条件に該当するレコードを取得。");
    MSG("レコード数が1で該当レコード数が1の場合。");

    Table<Integer,String> t0 = new TableEx<Integer,String>();
    Index<Integer,String> t = t0.getIndex(1, 2);

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    List<Map<Integer,String>> rL0 = t.select(1, "xxx");
    EQUAL(rL0.size(), 1);
    IDENTIFY(r, rL0.get(0));

    List<Map<Integer,String>> rL1 = t.select(2, "yyy");
    EQUAL(rL1.size(), 1);
    IDENTIFY(r, rL1.get(0));

    List<Map<Integer,String>> rL2 = t.select(3, "zzz");
    EQUAL(rL2.size(), 1);
    IDENTIFY(r, rL2.get(0));
  }

  public void getIndex_and_select_column_value_1()
  {
    MSG("レコード数が1で該当レコード数が0の場合。");

    Table<Integer,String> t0 = new TableEx<Integer,String>();
    Index<Integer,String> t = t0.getIndex(1, 2);

    Map<Integer,String> r = t.appendNew();
    r.put(1, "xxx");
    r.put(2, "yyy");
    r.put(3, "zzz");

    EQUAL(t.select(1, "XXX").size(), 0);

    EQUAL(t.select(2, "YYY").size(), 0);

    EQUAL(t.select(3, "ZZZ").size(), 0);
  }

  public void getIndex_and_select_column_value_2()
  {
    MSG("引数がヌルの場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    Map<String,String> r = t.appendNew();

    List<Map<String,String>> rL0 = t.select(null, null);
    EQUAL(rL0.size(), 0);

    r.put(null, null);
    List<Map<String,String>> rL1 = t.select(null, null);
    EQUAL(rL1.size(), 1); 
    IDENTIFY(rL1.get(0), r);

    r.put(null, "xxx");
    EQUAL(t.select(null, null).size(), 0);
    List<Map<String,String>> rL2 = t.select(null, "xxx");
    IDENTIFY(rL2.get(0), r);

    r.put("c0", null);
    EQUAL(t.select(null, null).size(), 0);
    List<Map<String,String>> rL3 = t.select("c0", null);
    IDENTIFY(rL3.get(0), r);
  }

  public void getIndex_and_select_column_value_3()
  {
    MSG("レコード数が空の場合。");

    TableEx<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    EQUAL(t.select(null, null).size(), 0);

    EQUAL(t.select("c0", null).size(), 0);

    EQUAL(t.select("c0", "v0").size(), 0);

    EQUAL(t.select(null, "v0").size(), 0);
  }

  public void getIndex_and_select_column_value_4()
  {
    MSG("レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    List<Map<String,String>> rL0 = t.select("c0", "v0");
    EQUAL(rL0.size(), 1);
    IDENTIFY(rL0.get(0), r0);

    List<Map<String,String>> rL1 = t.select("c1", "v4");
    EQUAL(rL1.size(), 1);
    IDENTIFY(rL1.get(0), r1);

    List<Map<String,String>> rL2 = t.select("c2", "v8");
    EQUAL(rL2.size(), 1);
    IDENTIFY(rL2.get(0), r2);
  }

  public void getIndex_and_select_column_value_5()
  {
    MSG("レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r1.put("c0", "v6");
    r1.put("c1", "v7");
    r1.put("c2", "v8");

    EQUAL(t.select("c0", "v9").size(), 0);
    EQUAL(t.select("c1", "v8").size(), 0);
    EQUAL(t.select("c2", "v7").size(), 0);
  }

  public void getIndex_and_select_column_value_6()
  {
    MSG("レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");
    
    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "vx");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "vy");
    r2.put("c2", "v2");

    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();

    List<Map<String,String>> rrL0 = t.select("c0", "v0");
    set.add(r0);
    set.add(r1);
    set.add(r2);
    EQUAL(rrL0.size(), 3);
    TRUE(set.contains(r0));
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));

    List<Map<String,String>> rrL1 = t.select("c1", "v1");
    set.clear();
    set.add(r0);
    set.add(r1);
    EQUAL(rrL1.size(), 2);
    TRUE(set.contains(r0));
    TRUE(set.contains(r1));

    List<Map<String,String>> rrL2 = t.select("c2", "v2");
    set.clear();
    set.add(r0);
    set.add(r2);
    EQUAL(rrL2.size(), 2);
    TRUE(set.contains(r0));
    TRUE(set.contains(r2));
  }

  public void getIndex_and_select_map()
  {
    MSG("インデックスを作成して、条件に該当するレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();

    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    List<Map<String,String>> rL0 = t.select(c0);
    EQUAL(rL0.size(), 1);
    IDENTIFY(rL0.get(0), r);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "v2");

    List<Map<String,String>> rL1 = t.select(c1);
    EQUAL(rL1.size(), 1);
    IDENTIFY(rL1.get(0), r);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "v2");

    List<Map<String,String>> rL2 = t.select(c2);
    EQUAL(rL2.size(), 1);
    IDENTIFY(rL2.get(0), r);
  }

  public void getIndex_and_select_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();

    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "vv");

    List<Map<String,String>> rL0 = t.select(c0);
    EQUAL(rL0.size(), 0);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "xx");

    List<Map<String,String>> rL1 = t.select(c1);
    EQUAL(rL1.size(), 0);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "yy");

    List<Map<String,String>> rL2 = t.select(c2);
    EQUAL(rL2.size(), 0);
  }

  public void getIndex_and_select_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t0 = new TableEx<String,String>();

    Index<String,String> t = t0.getIndex("c0");

    try {
      t.select(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void getIndex_and_select_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    EQUAL(t.select(c0).size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c1", null);
    t.deleteAll();
    EQUAL(t.columnCount(), 2);

    EQUAL(t.select(c0).size(), 0);
  }

  public void getIndex_and_select_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    List<Map<String,String>> rrL0 = t.select(c0);
    EQUAL(rrL0.size(), 1);
    IDENTIFY(rrL0.get(0), r0);

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c1", "v4");
    c1.put("c2", "v5");

    List<Map<String,String>> rrL1 = t.select(c1);
    EQUAL(rrL1.size(), 1);
    IDENTIFY(rrL1.get(0), r1);

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v6");
    c2.put("c1", "v7");
    c2.put("c2", "v8");

    List<Map<String,String>> rrL2 = t.select(c2);
    EQUAL(rrL2.size(), 1);
    IDENTIFY(rrL2.get(0), r2);
  }

  public void getIndex_and_select_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Table<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    EQUAL(t.select(c).size(), 0);
  }

  public void getIndex_and_select_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();

    Map<String,String> c = new HashMap<String,String>();
    set.add(r0);
    set.add(r1);
    set.add(r2);
    List<Map<String,String>> rL0 = t.select(c);
    EQUAL(rL0.size(), 3);
    TRUE(set.contains(r0));
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));

    c.put("c0", "v0");
    set.add(r0);
    set.add(r1);
    set.add(r2);
    List<Map<String,String>> rL1 = t.select(c);
    EQUAL(rL1.size(), 3);
    TRUE(set.contains(r0));
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));

    c.put("c2", "v3");
    set.add(r1);
    set.add(r2);
    List<Map<String,String>> rL2 = t.select(c);
    EQUAL(rL2.size(), 2);
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));
  }

  public void getIndex_and_select_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL0 = t.select(c);
    EQUAL(rL0.size(), 1);
    EQUAL(rL0.get(0), r);
  }

  public void getIndex_and_select_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Table<String,String> t = t0.getIndex("c0");

    Map<String,String> c = new HashMap<String,String>();

    EQUAL(t.select(c).size(), 0);
  }

  public void getIndex_and_select_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();

    Map<String,String> c = new HashMap<String,String>();
    set.add(r0);
    set.add(r1);
    set.add(r2);
    List<Map<String,String>> rL = t.select(c);
    EQUAL(rL.size(), 3);
    TRUE(set.contains(rL.get(0)));
    TRUE(set.contains(rL.get(1)));
    TRUE(set.contains(rL.get(2)));
  }

  public void getIndex_and_delete_map()
  {
    MSG("インデックスを作成して、条件に該当するレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    for (int i=0; i<3; i++) {
      TableEx<String,String> t0 = new TableEx<String,String>();
      Index<String,String> t = t0.getIndex("c0", "c1");
  
      Map<String,String> r = t.appendNew();
      r.put("c0", "v0");
      r.put("c1", "v1");
      r.put("c2", "v2");

      switch (i) {
      case 0 : {
          Map<String,String> c0 = new HashMap<String,String>();
          c0.put("c0", "v0");
          c0.put("c1", "v1");
      
          List<Map<String,String>> rL0 = t.delete(c0);
          EQUAL(rL0.size(), 1);
          IDENTIFY(rL0.get(0), r);
          EQUAL(t.recordCount(), 0);
          EQUAL(t.select(c0).size(), 0);
        } break;

      case 1 : {
          Map<String,String> c1 = new HashMap<String,String>();
          c1.put("c0", "v0");
          c1.put("c2", "v2");
  
          List<Map<String,String>> rL1 = t.delete(c1);
          EQUAL(rL1.size(), 1);
          IDENTIFY(rL1.get(0), r);
          EQUAL(t.recordCount(), 0);
          EQUAL(t.select(c1).size(), 0);
        } break;

      case 2 : {
          Map<String,String> c2 = new HashMap<String,String>();
          c2.put("c0", "v0");
          c2.put("c1", "v1");
          c2.put("c2", "v2");
    
          List<Map<String,String>> rL2 = t.delete(c2);
          EQUAL(rL2.size(), 1);
          IDENTIFY(rL2.get(0), r);
          EQUAL(t.recordCount(), 0);
          EQUAL(t.select(c2).size(), 0);
        } break;
      }
    }
  }

  public void getIndex_and_delete_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    for (int i=0; i<3; i++) {
      TableEx<String,String> t0 = new TableEx<String,String>();
      Index<String,String> t = t0.getIndex("c0", "c1");

      Map<String,String> r = t.appendNew();
      r.put("c0", "v0");
      r.put("c1", "v1");
      r.put("c2", "v2");

      switch (i) {
      case 0 : {
          Map<String,String> c0 = new HashMap<String,String>();
          c0.put("c0", "v0");
          c0.put("c1", "vv");
  
          List<Map<String,String>> rL0 = t.delete(c0);
          EQUAL(rL0.size(), 0);
          EQUAL(t.recordCount(), 1);
          EQUAL(t.select(c0).size(), 0);
        } break;

      case 1 : {
          Map<String,String> c1 = new HashMap<String,String>();
          c1.put("c0", "v0");
          c1.put("c2", "xx");

          List<Map<String,String>> rL1 = t.delete(c1);
          EQUAL(rL1.size(), 0);
          EQUAL(t.recordCount(), 1);
          EQUAL(t.select(c1).size(), 0);
        } break;

      case 2 : {
          Map<String,String> c2 = new HashMap<String,String>();
          c2.put("c0", "v0");
          c2.put("c1", "v1");
          c2.put("c2", "yy");

          List<Map<String,String>> rL2 = t.delete(c2);
          EQUAL(rL2.size(), 0);
          EQUAL(t.recordCount(), 1);
          EQUAL(t.select(c2).size(), 0);
        } break;
      }
    }
  }

  public void getIndex_and_delete_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    try {
      t.select(null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void getIndex_and_delete_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    EQUAL(t.delete(c0).size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c0", null);
    t.deleteAll();
  }

  public void getIndex_and_delete_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    for (int i=0; i<3; i++) { 
      Table<String,String> t0 = new TableEx<String,String>();
      Index<String,String> t = t0.getIndex("c0", "c1");
  
      Map<String,String> r0 = t.appendNew();
      r0.put("c0", "v0");
      r0.put("c1", "v1");
      r0.put("c2", "v2");
  
      Map<String,String> r1 = t.appendNew();
      r1.put("c0", "v3");
      r1.put("c1", "v4");
      r1.put("c2", "v5");
  
      Map<String,String> r2 = t.appendNew();
      r2.put("c0", "v6");
      r2.put("c1", "v7");
      r2.put("c2", "v8");

      Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();
  
      switch (i) {
      case 0: {
        Map<String,String> c0 = new HashMap<String,String>();
        c0.put("c0", "v0");
        c0.put("c1", "v1");
        List<Map<String,String>> rL0 = t.delete(c0);
        EQUAL(rL0.size(), 1);
        IDENTIFY(rL0.get(0), r0);
        EQUAL(t.recordCount(), 2);
        List<Map<String,String>> rL00 = t.select(new HashMap<String,String>());
        set.add(r1);
        set.add(r2);
        TRUE(set.contains(r1));
        TRUE(set.contains(r2));
        } break;

      case 1: {
        Map<String,String> c1 = new HashMap<String,String>();
        c1.put("c1", "v4");
        c1.put("c2", "v5");
  
        List<Map<String,String>> rL1 = t.delete(c1);
        EQUAL(rL1.size(), 1);
        IDENTIFY(rL1.get(0), r1);
        EQUAL(t.recordCount(), 2);
        List<Map<String,String>> rL11 = t.select(new HashMap<String,String>());
        set.add(r0);
        set.add(r2);
        TRUE(set.contains(r0));
        TRUE(set.contains(r2));
        } break;

      case 2: {
        Map<String,String> c2 = new HashMap<String,String>();
        c2.put("c2", "v6");
        c2.put("c2", "v7");
        c2.put("c2", "v8");

        List<Map<String,String>> rL2 = t.delete(c2);
        EQUAL(rL2.size(), 1);
        IDENTIFY(rL2.get(0), r2);
        EQUAL(t.recordCount(), 2);
        List<Map<String,String>> rL22 = t.select(new HashMap<String,String>());
        set.add(r0);
        set.add(r1);
        TRUE(set.contains(r0));
        TRUE(set.contains(r1));
        } break;
      }
    }  
  }

  public void getIndex_and_delete_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    EQUAL(t.delete(c).size(), 0);
    EQUAL(t.recordCount(), 3);
  }

  public void getIndex_and_delete_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    for (int i=0; i<3; i++) {
      Table<String,String> t0 = new TableEx<String,String>();
      Index<String,String> t = t0.getIndex("c0", "c1");
  
      Map<String,String> r0 = t.appendNew();
      r0.put("c0", "v0");
      r0.put("c1", "v1");
      r0.put("c2", "v2");
  
      Map<String,String> r1 = t.appendNew();
      r1.put("c0", "v0");
      r1.put("c1", "vx");
      r1.put("c2", "v3");
  
      Map<String,String> r2 = t.appendNew();
      r2.put("c0", "v0");
      r2.put("c1", "v1");
      r2.put("c2", "v3");

      Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();

      switch (i) {
      case 0: {
        Map<String,String> c = new HashMap<String,String>();

        List<Map<String,String>> rL0 = t.delete(c);
        EQUAL(rL0.size(), 3);
        set.add(r0);
        set.add(r1);
        set.add(r2);
        TRUE(set.contains(r0));
        TRUE(set.contains(r1));
        TRUE(set.contains(r2));
        EQUAL(t.recordCount(), 0);
        } break;
      case 1: {
        Map<String,String> c = new HashMap<String,String>();
        c.put("c0", "v0");
    
        List<Map<String,String>> rL1 = t.delete(c);
        EQUAL(rL1.size(), 3);
        set.add(r0);
        set.add(r1);
        set.add(r2);
        TRUE(set.contains(r0));
        TRUE(set.contains(r1));
        TRUE(set.contains(r2));
        EQUAL(t.recordCount(), 0);
        } break;
      case 2: {
        Map<String,String> c = new HashMap<String,String>();
        c.put("c2", "v3");
    
        List<Map<String,String>> rL2 = t.delete(c);
        EQUAL(rL2.size(), 2);
        set.add(r1);
        set.add(r2);
        TRUE(set.contains(r1));
        TRUE(set.contains(r2));
        EQUAL(t.recordCount(), 1);
        List<Map<String,String>> rL22 = t.select(new HashMap<String,String>());
        EQUAL(rL22.get(0), r0);
        } break;
      }
    }
  }

  public void getIndex_and_delete_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL0 = t.delete(c);
    EQUAL(rL0.size(), 1);
    EQUAL(rL0.get(0), r);
    EQUAL(t.recordCount(), 0);
  }

  public void getIndex_and_delete_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    Map<String,String> c = new HashMap<String,String>();

    EQUAL(t.delete(c).size(), 0);
  }

  public void getIndex_and_delete_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL = t.delete(c);

    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();
    set.add(r0);
    set.add(r1);
    set.add(r2);
    EQUAL(rL.size(), 3);
    TRUE(set.contains(r0));
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));
    EQUAL(t.recordCount(), 0);
  }

  public void getIndex_and_update_map()
  {
    MSG("インデックスを作成して、条件に該当するレコードを取得。");
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");
    r.put("c3", "v3");
    r.put("c4", "v4");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c3", "yIII");
    d0.put("c4", "yIV");

    List<Map<String,String>> rL0 = t.update(c0, d0);
    EQUAL(rL0.size(), 1);
    IDENTIFY(rL0.get(0), r);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "yIII");
    EQUAL(r.get("c4"), "yIV");

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "v2");

    Map<String,String> d1 = new HashMap<String,String>();
    d1.put("c3", "あ");
    d1.put("c4", "い");

    List<Map<String,String>> rL1 = t.update(c1, d1);
    EQUAL(rL1.size(), 1);
    IDENTIFY(rL1.get(0), r);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "あ");
    EQUAL(r.get("c4"), "い");

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "v2");

    Map<String,String> d2 = new HashMap<String,String>();
    d2.put("c3", "a");
    d2.put("c4", "i");

    List<Map<String,String>> rL2 = t.update(c2, d2);
    EQUAL(rL2.size(), 1);
    IDENTIFY(rL2.get(0), r);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "a");
    EQUAL(r.get("c4"), "i");
  }

  public void getIndex_and_update_map_1()
  {
    MSG("条件のカラムが複数、レコード数が1で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");
    r.put("c1", "v1");
    r.put("c2", "v2");
    r.put("c3", "v3");
    r.put("c4", "v4");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "vv");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c3", "XX");
    d0.put("c4", "YY");

    List<Map<String,String>> rL0 = t.update(c0, d0);
    EQUAL(rL0.size(), 0);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "v3");
    EQUAL(r.get("c4"), "v4");

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c2", "xx");

    Map<String,String> d1 = new HashMap<String,String>();
    d1.put("c3", "XX");
    d1.put("c4", "YY");

    List<Map<String,String>> rL1 = t.update(c1, d1);
    EQUAL(rL1.size(), 0);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "v3");
    EQUAL(r.get("c4"), "v4");

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c1", "v1");
    c2.put("c2", "yy");

    Map<String,String> d2 = new HashMap<String,String>();
    d2.put("c3", "XX");
    d2.put("c4", "YY");

    List<Map<String,String>> rL2 = t.update(c2, d2);
    EQUAL(rL2.size(), 0);
    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c1"), "v1");
    EQUAL(r.get("c2"), "v2");
    EQUAL(r.get("c3"), "v3");
    EQUAL(r.get("c4"), "v4");
  }

  public void getIndex_and_update_map_2()
  {
    MSG("引数がヌルの場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Table<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();

    try {
      t.update(null, d);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }

    try {
      t.update(c, null);
      NG();
    } catch (AssertionError e) {
      OK(e);
    }
  }

  public void getIndex_and_update_map_3()
  {
    MSG("条件のカラムが複数、レコード数が空の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Table<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c0", "V0");
    d0.put("c1", "V1");

    EQUAL(t.update(c0, d0).size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", null);
    r0.put("c1", null);
    t.deleteAll();
    EQUAL(t.columnCount(), 2);

    EQUAL(t.update(c0, d0).size(), 0);
  }

  public void getIndex_and_update_map_4()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "V3");
    r0.put("c4", "V4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");
    r1.put("c3", "V3");
    r1.put("c4", "V4");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");
    r2.put("c3", "V3");
    r2.put("c4", "V4");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    c0.put("c1", "v1");

    Map<String,String> d0 = new HashMap<String,String>();
    d0.put("c3", "VV3");
    d0.put("c4", "VV4");

    List<Map<String,String>> rrL0 = t.update(c0, d0);
    EQUAL(rrL0.size(), 1);
    IDENTIFY(rrL0.get(0), r0);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "VV3");
    EQUAL(r0.get("c4"), "VV4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r1.get("c3"), "V3");
    EQUAL(r1.get("c4"), "V4");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
    EQUAL(r2.get("c3"), "V3");
    EQUAL(r2.get("c4"), "V4");

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c1", "v4");
    c1.put("c2", "v5");

    Map<String,String> d1 = new HashMap<String,String>();
    d1.put("c3", "XXXXXX");
    d1.put("c4", "YYYYYY");

    List<Map<String,String>> rrL1 = t.update(c1, d1);
    EQUAL(rrL1.size(), 1);
    IDENTIFY(rrL1.get(0), r1);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "VV3");
    EQUAL(r0.get("c4"), "VV4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r1.get("c3"), "XXXXXX");
    EQUAL(r1.get("c4"), "YYYYYY");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
    EQUAL(r2.get("c3"), "V3");
    EQUAL(r2.get("c4"), "V4");

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v6");
    c2.put("c1", "v7");
    c2.put("c2", "v8");

    Map<String,String> d2 = new HashMap<String,String>();
    d2.put("c3", "あいうえお");
    d2.put("c4", "かきくけこ");

    List<Map<String,String>> rrL2 = t.update(c2, d2);
    EQUAL(rrL2.size(), 1);
    IDENTIFY(rrL2.get(0), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "VV3");
    EQUAL(r0.get("c4"), "VV4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r1.get("c3"), "XXXXXX");
    EQUAL(r1.get("c4"), "YYYYYY");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
    EQUAL(r2.get("c3"), "あいうえお");
    EQUAL(r2.get("c4"), "かきくけこ");
  }

  public void getIndex_and_update_map_5()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Table<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "v3");
    r0.put("c4", "v4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v3");
    r1.put("c1", "v4");
    r1.put("c2", "v5");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v6");
    r2.put("c1", "v7");
    r2.put("c2", "v8");

    Map<String,String> c = new HashMap<String,String>();
    c.put("c0", "cA");
    c.put("c1", "cB");
    c.put("c2", "cC");

    Map<String,String> d = new HashMap<String,String>();
    c.put("c3", "d0");
    c.put("c4", "d1");

    EQUAL(t.update(c, d).size(), 0);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "v3");
    EQUAL(r0.get("c4"), "v4");
    EQUAL(r1.get("c0"), "v3");
    EQUAL(r1.get("c1"), "v4");
    EQUAL(r1.get("c2"), "v5");
    EQUAL(r2.get("c0"), "v6");
    EQUAL(r2.get("c1"), "v7");
    EQUAL(r2.get("c2"), "v8");
  }

  public void getIndex_and_update_map_6()
  {
    MSG("条件のカラムが複数、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "v3");
    r0.put("c4", "v4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();

    List<Map<String,String>> rL0 = t.update(c, d);
    EQUAL(rL0.size(), 3);
    set.add(r0);
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(r0));
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "XX");
    EQUAL(r0.get("c4"), "YY");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "XX");
    EQUAL(r1.get("c4"), "YY");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "XX");
    EQUAL(r2.get("c4"), "YY");

    c.put("c0", "v0");
    d.put("c3", "あいうえお");
    d.put("c4", "かきくけこ");

    List<Map<String,String>> rL1 = t.update(c, d);
    EQUAL(rL1.size(), 3);
    set.add(r0);
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(r0));
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "あいうえお");
    EQUAL(r0.get("c4"), "かきくけこ");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "あいうえお");
    EQUAL(r1.get("c4"), "かきくけこ");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "あいうえお");
    EQUAL(r2.get("c4"), "かきくけこ");

    c.put("c2", "v3");
    d.put("c3", "ABCDEFG");
    d.put("c4", "HIJKLMN");

    List<Map<String,String>> rL2 = t.update(c, d);
    EQUAL(rL2.size(), 2);
    set.add(r1);
    set.add(r2);
    TRUE(set.contains(r1));
    TRUE(set.contains(r2));
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "あいうえお");
    EQUAL(r0.get("c4"), "かきくけこ");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "ABCDEFG");
    EQUAL(r1.get("c4"), "HIJKLMN");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "ABCDEFG");
    EQUAL(r2.get("c4"), "HIJKLMN");
  }

  public void getIndex_and_update_map_7()
  {
    MSG("条件のカラムが0、レコード数が1で該当レコード数が1の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0");

    Map<String,String> r = t.appendNew();
    r.put("c0", "v0");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    List<Map<String,String>> rL0 = t.update(c, d);
    EQUAL(rL0.size(), 1);
    EQUAL(rL0.get(0), r);

    EQUAL(r.get("c0"), "v0");
    EQUAL(r.get("c3"), "XX");
    EQUAL(r.get("c4"), "YY");
  }

  public void getIndex_and_update_map_8()
  {
    MSG("条件のカラムが0、レコード数が0で該当レコード数が0の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c3");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    EQUAL(t.update(c, d).size(), 0);
  }

  public void getIndex_and_update_map_9()
  {
    MSG("条件のカラムが0、レコード数が複数で該当レコード数が複数の場合。");

    Table<String,String> t0 = new TableEx<String,String>();
    Index<String,String> t = t0.getIndex("c0", "c1");

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "v3");
    r0.put("c4", "v4");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    Set<Map<String,String>> set = new IdentityHashSet<Map<String,String>>();
    set.add(r0);
    set.add(r1);
    set.add(r2);

    List<Map<String,String>> rL = t.update(c, d);
    EQUAL(rL.size(), 3);
    TRUE(set.contains(rL.get(0)));
    TRUE(set.contains(rL.get(1)));
    TRUE(set.contains(rL.get(2)));

    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "XX");
    EQUAL(r0.get("c4"), "YY");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "XX");
    EQUAL(r1.get("c4"), "YY");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "XX");
    EQUAL(r2.get("c4"), "YY");
  }

  public void addTrigger_and_appendNew()
  {
    MSG("トリガを追加して、レコードを追加。");
    MSG("空のテーブルにレコードを追加。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 0);

    for (int i=0; i<10; i++) {
      t.appendNew();
      EQUAL(t.recordCount(), i+1);
      EQUAL(t.columnCount(), 0);
    }
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null##########");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$$$$$$$$");
  }

  public void addTrigger_and_appendNew_1()
  {
    MSG("追加したレコードに対してputメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}");

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}{C1=V1}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}{C1=V1}");

    Set<String> s = new HashSet<String>();
    s.add("C0");
    s.add("C1");
    EQUAL(s, r.keySet());

    Set<String> s1 = new HashSet<String>();
    Enumeration<String> e1 = t.columns();
    while (e1.hasMoreElements()) {
      s1.add(e1.nextElement());
    }
    EQUAL(s, s1);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}{C1=V1}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}{C1=V1}");
  }

  public void addTrigger_and_appendNew_2()
  {
    MSG("追加したレコードに対してremoveメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}");

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}{C1=V1}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}{C1=V1}");

    EQUAL(r.remove("C0"), "V0");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(r.get("C0"), null);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}{C1=V1}{C0=null}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}{C1=V1}{C0=null}");
  }

  public void addTrigger_and_appendNew_3()
  {
    MSG("追加したレコードに対してputAllメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}");

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}{C1=V1}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}{C1=V1}");

    Map<String,String> m = new HashMap<String,String>();
    m.put("C0", "あいうえお");
    m.put("C1", "かきくけこ");
    m.put("C2", "さしすせそ");

    r.putAll(m);
    EQUAL(r.size(), 3);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 3);
    EQUAL(r.get("C0"), "あいうえお");
    EQUAL(r.get("C1"), "かきくけこ");
    EQUAL(r.get("C2"), "さしすせそ");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{C0=V0}{C1=V1}{C0=あいうえお, C1=かきくけこ, C2=さしすせそ}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{C0=V0}{C1=V1}{C0=あいうえお, C1=かきくけこ, C2=さしすせそ}");
  }

  public void addTrigger_and_appendNew_4()
  {
    MSG("追加したレコードに対してclearメソッドを実行。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");

    r.put("C0", "V0");
    EQUAL(r.size(), 1);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 1);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}");

    r.put("C1", "V1");
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0}{C1=V1}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0}{C1=V1}");

    r.clear();
    EQUAL(r.size(), 2);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 2);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{C0=V0}{C1=V1}{C0=null, C1=null}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{C0=V0}{C1=V1}{C0=null, C1=null}");
  }

  public void addTrigger_and_appendNew_5()
  {
    MSG("clearメソッド実行時にトリガでレコードの内容が変更された場合。");

    TableEx<String,String> t = new TableEx<String,String>();

    final Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap) {
      static final long serialVersionUID = -1L;
      @Override
      protected void preUpdate(
      Table<String,String> t, Map<String,String> r, Map<String,String> d) {
        r.put("C9", "V9");
        d.put("D1", "W1");
        triggerLogMap.put("preUpdate",
          triggerLogMap.get("preUpdate") + map2string(d));
      }
      @Override
      protected void postUpdate(
      Table<String,String> t, Map<String,String> r, Map<String,String> d) {
        r.put("C8", "V8");
        d.put("D2", "W2");
        triggerLogMap.put("postUpdate",
          triggerLogMap.get("postUpdate") + map2string(d));
      }
    });

    EQUAL(t.recordCount(), 0);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r = t.appendNew();
    EQUAL(r.size(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 0);
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");

    r.put("C0", "V0");
    EQUAL(r.size(), 4);
    EQUAL(r.get("C0"), "V0");
    EQUAL(r.get("C8"), "V8");
    EQUAL(r.get("C9"), "V9");
    EQUAL(r.get("D1"), "W1");
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 4);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{C0=V0, D1=W1}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{C0=V0, D1=W1, D2=W2}");

    r.put("C1", "V1");
    EQUAL(r.size(), 5);
    EQUAL(r.get("C0"), "V0");
    EQUAL(r.get("C1"), "V1");
    EQUAL(r.get("C8"), "V8");
    EQUAL(r.get("C9"), "V9");
    EQUAL(r.get("D1"), "W1");
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 5);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{C0=V0, D1=W1}{C1=V1, D1=W1}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{C0=V0, D1=W1, D2=W2}{C1=V1, D1=W1, D2=W2}");

    r.remove("C0");
    EQUAL(r.size(), 5);
    EQUAL(r.get("C0"), null);
    EQUAL(r.get("C1"), "V1");
    EQUAL(r.get("C8"), "V8");
    EQUAL(r.get("C9"), "V9");
    EQUAL(r.get("D1"), "W1");
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 5);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{C0=V0, D1=W1}{C1=V1, D1=W1}{C0=null, D1=W1}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{C0=V0, D1=W1, D2=W2}{C1=V1, D1=W1, D2=W2}{C0=null, D1=W1, D2=W2}");

    r.clear();
    EQUAL(r.size(), 5);
    EQUAL(r,r);
    NULL(r.get("C0"));
    NULL(r.get("C1"));
    EQUAL(r.get("C8"), "V8");
    NULL(r.get("C9"));
    EQUAL(r.get("D1"), "W1");
    EQUAL(t.recordCount(), 1);
    EQUAL(t.columnCount(), 5);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{C0=V0, D1=W1}{C1=V1, D1=W1}{C0=null, D1=W1}{C0=null, C1=null, C8=null, C9=null, D1=W1}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{C0=V0, D1=W1, D2=W2}{C1=V1, D1=W1, D2=W2}{C0=null, D1=W1, D2=W2}{C0=null, C1=null, C8=null, C9=null, D1=W1, D2=W2}");
  }

  public void addTrigger_and_deleteAll()
  {
    MSG("トリガを追加して、レコードの全削除。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    EQUAL(t.columnCount(), 0);
    EQUAL(t.recordCount(), 1);
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");

    r0.put("c0", "a");
    r0.put("c1", "b");
    r0.put("c2", "c");
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 1);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=a}{c1=b}{c2=c}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=a}{c1=b}{c2=c}");

    Map<String,String> r1 = t.appendNew();
    Map<String,String> r2 = t.appendNew();
    Map<String,String> r3 = t.appendNew();
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 4);
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null####");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=a}{c1=b}{c2=c}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=a}{c1=b}{c2=c}");

    t.deleteAll();
    EQUAL(t.columnCount(), 3);
    EQUAL(t.recordCount(), 0);
    EQUAL(triggerLogMap.size(), 6);
    EQUAL(triggerLogMap.get("preAppend"), "null####");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=a}{c1=b}{c2=c}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=a}{c1=b}{c2=c}");
    EQUAL(triggerLogMap.get("preDelete"), "null%%%%");
    EQUAL(triggerLogMap.get("postDelete"), "null&&&&");
  }

  public void addTrigger_and_exists_column_value()
  {
    MSG("トリガを追加して、条件に該当するレコードの存在を確認。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    EQUAL(triggerLogMap.size(), 2);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");

    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null##");
    EQUAL(triggerLogMap.get("postAppend"), "null$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v1");
    r2.put("c1", "v4");
    r2.put("c2", "v2");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}{c0=v1}{c1=v4}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}{c0=v1}{c1=v4}{c2=v2}");

    TRUE(t.exists("c0", "v0"));
    TRUE(t.exists("c1", "v1"));
    TRUE(t.exists("c2", "v2"));

    FALSE(t.exists("c0", "x"));
    FALSE(t.exists("c1", "y"));
    FALSE(t.exists("c2", "z"));

    FALSE(t.exists("c0", null));
    FALSE(t.exists("c1", null));
    FALSE(t.exists("c2", null));
  }

  public void addTrigger_and_exists_map()
  {
    MSG("トリガを追加して、条件に該当するレコードの存在を確認。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "v3");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null##");
    EQUAL(triggerLogMap.get("postAppend"), "null$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v4");
    r2.put("c2", "v2");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}{c0=v0}{c1=v4}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}{c0=v0}{c1=v4}{c2=v2}");

    Map<String,String> c0 = new HashMap<String,String>();
    c0.put("c0", "v0");
    TRUE(t.exists(c0));

    Map<String,String> c1 = new HashMap<String,String>();
    c1.put("c0", "v0");
    c1.put("c1", "v1");
    TRUE(t.exists(c1));

    Map<String,String> c1x = new HashMap<String,String>();
    c1x.put("c0", "v0");
    c1x.put("c1", "xx");
    FALSE(t.exists(c1x));

    Map<String,String> c2 = new HashMap<String,String>();
    c2.put("c0", "v0");
    c2.put("c2", "v2");
    TRUE(t.exists(c2));

    Map<String,String> c2x = new HashMap<String,String>();
    c2x.put("c0", "v0");
    c2x.put("c2", "xx");
    FALSE(t.exists(c2x));

    Map<String,String> c3 = new HashMap<String,String>();
    c3.put("c0", "v0");
    c3.put("c1", "v1");
    c3.put("c2", "v2");
    TRUE(t.exists(c3));

    Map<String,String> c4 = new HashMap<String,String>();
    c4.put("c0", null);
    FALSE(t.exists(c4));

    Map<String,String> c5 = new HashMap<String,String>();
    c5.put("c0", "v0");
    c5.put("c1", null);
    FALSE(t.exists(c5));

    Map<String,String> c6 = new HashMap<String,String>();
    c6.put("c0", "v0");
    c6.put("c1", "v1");
    c6.put("c2", null);
    FALSE(t.exists(c6));

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}{c0=v0}{c1=v4}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=v3}{c0=v0}{c1=v4}{c2=v2}");
  }

  public void addTrigger_and_selectFirst_column_value()
  {
    MSG("トリガを追加して、条件に該当する最初のレコードを取得。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "vx");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null##");
    EQUAL(triggerLogMap.get("postAppend"), "null$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "vy");
    r2.put("c2", "v2");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");

    Map<String,String> rr0 = t.selectFirst("c0", "v0");
    IDENTIFY(rr0, r0);

    Map<String,String> rr1 = t.selectFirst("c1", "v1");
    IDENTIFY(rr1, r0);

    Map<String,String> rr2 = t.selectFirst("c2", "v2");
    IDENTIFY(rr2, r0);

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");
  }

  public void addTrigger_and_selectFirst_map()
  {
    MSG("トリガを追加して、条件に該当する最初のレコードを取得。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null##");
    EQUAL(triggerLogMap.get("postAppend"), "null$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");

    Map<String,String> c = new HashMap<String,String>();

    EQUAL(r0, t.selectFirst(c));

    c.put("c0", "v0");

    EQUAL(r0, t.selectFirst(c));

    c.put("c2", "v3");

    EQUAL(r1, t.selectFirst(c));

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
  }

  public void addTrigger_and_select_column_value()
  {
    MSG("トリガを追加して、条件に該当するレコードを取得。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "v1");
    r1.put("c2", "vx");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null##");
    EQUAL(triggerLogMap.get("postAppend"), "null$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "vy");
    r2.put("c2", "v2");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");

    List<Map<String,String>> rrL0 = t.select("c0", "v0");
    EQUAL(rrL0.size(), 3);
    IDENTIFY(rrL0.get(0), r0);
    IDENTIFY(rrL0.get(1), r1);
    IDENTIFY(rrL0.get(2), r2);

    List<Map<String,String>> rrL1 = t.select("c1", "v1");
    EQUAL(rrL1.size(), 2);
    IDENTIFY(rrL1.get(0), r0);
    IDENTIFY(rrL1.get(1), r1);

    List<Map<String,String>> rrL2 = t.select("c2", "v2");
    EQUAL(rrL2.size(), 2);
    IDENTIFY(rrL2.get(0), r0);
    IDENTIFY(rrL2.get(1), r2);

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=v1}{c2=vx}{c0=v0}{c1=vy}{c2=v2}");
  }

  public void addTrigger_and_select_map()
  {
    MSG("トリガを追加して、条件に該当するレコードを取得。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null##");
    EQUAL(triggerLogMap.get("postAppend"), "null$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");

    Map<String,String> c = new HashMap<String,String>();

    List<Map<String,String>> rL0 = t.select(c);
    EQUAL(rL0.size(), 3);
    IDENTIFY(rL0.get(0), r0);
    IDENTIFY(rL0.get(1), r1);
    IDENTIFY(rL0.get(2), r2);

    c.put("c0", "v0");

    List<Map<String,String>> rL1 = t.select(c);
    EQUAL(rL1.size(), 3);
    IDENTIFY(rL1.get(0), r0);
    IDENTIFY(rL1.get(1), r1);
    IDENTIFY(rL1.get(2), r2);

    c.put("c2", "v3");

    List<Map<String,String>> rL2 = t.select(c);
    EQUAL(rL2.size(), 2);
    IDENTIFY(rL2.get(0), r1);
    IDENTIFY(rL2.get(1), r2);

    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"),
      "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
  }

  public void addTrigger_and_delete_map()
  {
    MSG("トリガを追加して、条件に該当するレコードを取得。");

    for (int i=0; i<3; i++) {
      TableEx<String,String> t = new TableEx<String,String>();

      Map<String,String> triggerLogMap = new HashMap<String,String>();
      t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
      EQUAL(triggerLogMap.size(), 0);
  
      Map<String,String> r0 = t.appendNew();
      r0.put("c0", "v0");
      r0.put("c1", "v1");
      r0.put("c2", "v2");
      EQUAL(triggerLogMap.size(), 4);
      EQUAL(triggerLogMap.get("preAppend"), "null#");
      EQUAL(triggerLogMap.get("postAppend"), "null$");
      EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
      EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}");
  
      Map<String,String> r1 = t.appendNew();
      r1.put("c0", "v0");
      r1.put("c1", "vx");
      r1.put("c2", "v3");
      EQUAL(triggerLogMap.size(), 4);
      EQUAL(triggerLogMap.get("preAppend"), "null##");
      EQUAL(triggerLogMap.get("postAppend"), "null$$");
      EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}");
      EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}");
  
      Map<String,String> r2 = t.appendNew();
      r2.put("c0", "v0");
      r2.put("c1", "v1");
      r2.put("c2", "v3");
      EQUAL(triggerLogMap.size(), 4);
      EQUAL(triggerLogMap.get("preAppend"), "null###");
      EQUAL(triggerLogMap.get("postAppend"), "null$$$");
      EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
      EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");

      switch (i) {
      case 0: {
        Map<String,String> c = new HashMap<String,String>();

        List<Map<String,String>> rL0 = t.delete(c);
        EQUAL(rL0.size(), 3);
        IDENTIFY(rL0.get(0), r0);
        IDENTIFY(rL0.get(1), r1);
        IDENTIFY(rL0.get(2), r2);
        EQUAL(t.recordCount(), 0);

        EQUAL(triggerLogMap.size(), 6);
        EQUAL(triggerLogMap.get("preAppend"), "null###");
        EQUAL(triggerLogMap.get("postAppend"), "null$$$");
        EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
        EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
        EQUAL(triggerLogMap.get("preDelete"), "null%%%");
        EQUAL(triggerLogMap.get("postDelete"), "null&&&");
        } break;
      case 1: {
        Map<String,String> c = new HashMap<String,String>();
        c.put("c0", "v0");
    
        List<Map<String,String>> rL1 = t.delete(c);
        EQUAL(rL1.size(), 3);
        IDENTIFY(rL1.get(0), r0);
        IDENTIFY(rL1.get(1), r1);
        IDENTIFY(rL1.get(2), r2);
        EQUAL(t.recordCount(), 0);

        EQUAL(triggerLogMap.size(), 6);
        EQUAL(triggerLogMap.get("preAppend"), "null###");
        EQUAL(triggerLogMap.get("postAppend"), "null$$$");
        EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
        EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
        EQUAL(triggerLogMap.get("preDelete"), "null%%%");
        EQUAL(triggerLogMap.get("postDelete"), "null&&&");
        } break;
      case 2: {
        Map<String,String> c = new HashMap<String,String>();
        c.put("c2", "v3");
    
        List<Map<String,String>> rL2 = t.delete(c);
        EQUAL(rL2.size(), 2);
        IDENTIFY(rL2.get(0), r1);
        IDENTIFY(rL2.get(1), r2);
        EQUAL(t.recordCount(), 1);
        List<Map<String,String>> rL22 = t.select(new HashMap<String,String>());
        EQUAL(rL22.get(0), r0);

        EQUAL(triggerLogMap.size(), 6);
        EQUAL(triggerLogMap.get("preAppend"), "null###");
        EQUAL(triggerLogMap.get("postAppend"), "null$$$");
        EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
        EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
        EQUAL(triggerLogMap.get("preDelete"), "null%%");
        EQUAL(triggerLogMap.get("postDelete"), "null&&");
        } break;
      }
    }
  }

  public void addTrigger_and_update_map_6()
  {
    MSG("トリガを追加して、条件に該当するレコードを取得。");

    TableEx<String,String> t = new TableEx<String,String>();

    Map<String,String> triggerLogMap = new HashMap<String,String>();
    t.addTrigger(new TriggerEx<String,String>(triggerLogMap));
    EQUAL(triggerLogMap.size(), 0);

    Map<String,String> r0 = t.appendNew();
    r0.put("c0", "v0");
    r0.put("c1", "v1");
    r0.put("c2", "v2");
    r0.put("c3", "v3");
    r0.put("c4", "v4");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null#");
    EQUAL(triggerLogMap.get("postAppend"), "null$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}");

    Map<String,String> r1 = t.appendNew();
    r1.put("c0", "v0");
    r1.put("c1", "vx");
    r1.put("c2", "v3");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null##");
    EQUAL(triggerLogMap.get("postAppend"), "null$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}");

    Map<String,String> r2 = t.appendNew();
    r2.put("c0", "v0");
    r2.put("c1", "v1");
    r2.put("c2", "v3");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}");

    Map<String,String> c = new HashMap<String,String>();

    Map<String,String> d = new HashMap<String,String>();
    d.put("c3", "XX");
    d.put("c4", "YY");

    List<Map<String,String>> rL0 = t.update(c, d);
    EQUAL(rL0.size(), 3);
    IDENTIFY(rL0.get(0), r0);
    IDENTIFY(rL0.get(1), r1);
    IDENTIFY(rL0.get(2), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "XX");
    EQUAL(r0.get("c4"), "YY");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "XX");
    EQUAL(r1.get("c4"), "YY");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "XX");
    EQUAL(r2.get("c4"), "YY");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=XX, c4=YY}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=XX, c4=YY}");

    c.put("c0", "v0");
    d.put("c3", "あいうえお");
    d.put("c4", "かきくけこ");

    List<Map<String,String>> rL1 = t.update(c, d);
    EQUAL(rL1.size(), 3);
    IDENTIFY(rL1.get(0), r0);
    IDENTIFY(rL1.get(1), r1);
    IDENTIFY(rL1.get(2), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "あいうえお");
    EQUAL(r0.get("c4"), "かきくけこ");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "あいうえお");
    EQUAL(r1.get("c4"), "かきくけこ");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "あいうえお");
    EQUAL(r2.get("c4"), "かきくけこ");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}");

    c.put("c2", "v3");
    d.put("c3", "ABCDEFG");
    d.put("c4", "HIJKLMN");

    List<Map<String,String>> rL2 = t.update(c, d);
    EQUAL(rL2.size(), 2);
    IDENTIFY(rL2.get(0), r1);
    IDENTIFY(rL2.get(1), r2);
    EQUAL(r0.get("c0"), "v0");
    EQUAL(r0.get("c1"), "v1");
    EQUAL(r0.get("c2"), "v2");
    EQUAL(r0.get("c3"), "あいうえお");
    EQUAL(r0.get("c4"), "かきくけこ");
    EQUAL(r1.get("c0"), "v0");
    EQUAL(r1.get("c1"), "vx");
    EQUAL(r1.get("c2"), "v3");
    EQUAL(r1.get("c3"), "ABCDEFG");
    EQUAL(r1.get("c4"), "HIJKLMN");
    EQUAL(r2.get("c0"), "v0");
    EQUAL(r2.get("c1"), "v1");
    EQUAL(r2.get("c2"), "v3");
    EQUAL(r2.get("c3"), "ABCDEFG");
    EQUAL(r2.get("c4"), "HIJKLMN");
    EQUAL(triggerLogMap.size(), 4);
    EQUAL(triggerLogMap.get("preAppend"), "null###");
    EQUAL(triggerLogMap.get("postAppend"), "null$$$");
    EQUAL(triggerLogMap.get("preUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}{c3=ABCDEFG, c4=HIJKLMN}{c3=ABCDEFG, c4=HIJKLMN}");
    EQUAL(triggerLogMap.get("postUpdate"), "null{c0=v0}{c1=v1}{c2=v2}{c3=v3}{c4=v4}{c0=v0}{c1=vx}{c2=v3}{c0=v0}{c1=v1}{c2=v3}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=XX, c4=YY}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}{c3=あいうえお, c4=かきくけこ}{c3=ABCDEFG, c4=HIJKLMN}{c3=ABCDEFG, c4=HIJKLMN}");

  }
}

