private String getQuery(Object[] row) throws SQLException {
   StatementBuilder buff = new StatementBuilder();
   if (schema != null) {
     buff.append(StringUtils.quoteIdentifier(schema)).append('.');
   }
   buff.append(StringUtils.quoteIdentifier(table)).append(" WHERE ");
   for (int columnIndex : keys) {
     buff.appendExceptFirst(" AND ");
     buff.append(StringUtils.quoteIdentifier(columns[columnIndex]));
     Object o = row[columnIndex];
     if (o == null) {
       buff.append(" IS NULL");
     } else {
       buff.append('=').append(FullText.quoteSQL(o, columnTypes[columnIndex]));
     }
   }
   return buff.toString();
 }
 /**
  * Add the existing data to the index.
  *
  * @param conn the database connection
  * @param schema the schema name
  * @param table the table name
  */
 protected static void indexExistingRows(Connection conn, String schema, String table)
     throws SQLException {
   FullTextLucene.FullTextTrigger existing = new FullTextLucene.FullTextTrigger();
   existing.init(conn, schema, null, table, false, Trigger.INSERT);
   String sql =
       "SELECT * FROM "
           + StringUtils.quoteIdentifier(schema)
           + "."
           + StringUtils.quoteIdentifier(table);
   ResultSet rs = conn.createStatement().executeQuery(sql);
   int columnCount = rs.getMetaData().getColumnCount();
   while (rs.next()) {
     Object[] row = new Object[columnCount];
     for (int i = 0; i < columnCount; i++) {
       row[i] = rs.getObject(i + 1);
     }
     existing.insert(row, false);
   }
   existing.commitIndex();
 }
 /**
  * Create the trigger.
  *
  * @param conn the database connection
  * @param schema the schema name
  * @param table the table name
  */
 protected static void createTrigger(Connection conn, String schema, String table)
     throws SQLException {
   Statement stat = conn.createStatement();
   String trigger =
       StringUtils.quoteIdentifier(schema)
           + "."
           + StringUtils.quoteIdentifier(TRIGGER_PREFIX + table);
   stat.execute("DROP TRIGGER IF EXISTS " + trigger);
   StringBuilder buff = new StringBuilder("CREATE TRIGGER IF NOT EXISTS ");
   // the trigger is also called on rollback because transaction rollback
   // will not undo the changes in the Lucene index
   buff.append(trigger)
       .append(" AFTER INSERT, UPDATE, DELETE, ROLLBACK ON ")
       .append(StringUtils.quoteIdentifier(schema))
       .append('.')
       .append(StringUtils.quoteIdentifier(table))
       .append(" FOR EACH ROW CALL \"")
       .append(FullTextLucene2.FullTextTrigger.class.getName())
       .append('\"');
   stat.execute(buff.toString());
 }