// create table
  public double createTable(Table t) {
    switch (t.type.getId()) {
        // standard table
      case TABLE:
        if (t.partitions == null) return execute("CREATE " + t.toString() + ";");
        else {
          double timeToCreate = 0;
          List<Table> partitionTables = TableUtils.perPartitionTables(t);
          for (Table partitionT : partitionTables)
            timeToCreate += execute("CREATE " + partitionT.toString() + ";");
          return timeToCreate;
        }

        // column grouped table
      case CTABLE:
        if (t.partitions == null)
          // c_segment_size=10,c_buffer_size=1,c_partitions="1,2|3"
          return execute("CREATE " + t.toString() + ";");
        else {
          // _TODO: create a CTable in the modified postgres
          return execute(
              "CREATE "
                  + t.toString()
                  + " WITH (c_buffer_size=1000,c_partitions=\""
                  + PartitioningUtils.partitioningString(t.partitions)
                  + "\");");
        }

        // invalid table type
      default:
        throw new UnsupportedOperationException("Unknown table type !");
    }
  }
  // bulk load
  public double loadTable(Table t, String dataFile, String delimiter) {
    switch (t.type.getId()) {
      case TABLE:
        if (t.partitions == null)
          return execute(
              "COPY " + t.name + " FROM '" + dataFile + "' DELIMITER '" + delimiter + "'");
        else {
          this.t.reset();
          this.t.start();

          List<Table> partitionTables = TableUtils.perPartitionTables(t);

          TableRowIterator itr = new TableRowIterator(t, dataFile, delimiter);
          int count = 0;
          while (itr.hasNext()) {
            TableRow row = itr.next();
            for (TIntIterator keyit = t.partitions.keySet().iterator(); keyit.hasNext(); ) {
              int key = keyit.next();

              TableRow partialRow =
                  TableRowUtils.partialTableRow(
                      row, partitionTables.get(key), t.partitions.get(key).toArray());
              partialRow.add(count);
              insertRow(partitionTables.get(key), partialRow);
            }
            count++;
            if (count % 10000 == 0) log("Inserted " + count + " rows");
          }
          close();
          this.t.stop();
          return this.t.getElapsedTime();
        }
      case CTABLE:
        this.t.reset();
        this.t.start();
        TableRowIterator itr = new TableRowIterator(t, dataFile, delimiter);
        int count = 0;
        while (itr.hasNext()) {
          insertRow(t, itr.next());
          count++;
          if (count % 10000 == 0) log("Inserted " + count + " rows");
        }
        this.t.stop();
        return this.t.getElapsedTime();
      default:
        throw new UnsupportedOperationException("Unknown table type !");
    }
  }
  // execute drop table query
  public void dropTable(Table t) {
    switch (t.type.getId()) {
      case TABLE:
        if (t.partitions == null) execute("DROP TABLE IF EXISTS " + t.name);
        else {
          List<Table> partitionTables = TableUtils.perPartitionTables(t);
          for (Table pT : partitionTables) execute("DROP TABLE IF EXISTS " + pT.name);
        }
        break;

      case CTABLE:
        execute("DROP CTABLE IF EXISTS " + t.name);
        break;
      default:
        throw new UnsupportedOperationException("Unknown table type !");
    }
  }