protected void validateColumn(int rowNo, int colNo, Vector v, DBConnection conn) {
   if (rowNo < 0 || rowNo > getRowCount() || colNo < 0 || colNo > getColumnCount()) return;
   DSColumnDescriptor col = _desc.getColumn(colNo);
   boolean remoteRules = false;
   for (int i = 0; i < col.getRuleCount(); i++) {
     try {
       ValidationRule r = col.getRule(i);
       if (r.getRuleType() == ValidationRule.TYPE_REMOTE) remoteRules = true;
       else r.evaluateRule(this, rowNo, colNo, conn);
     } catch (DataStoreException ex) {
       ex.setRowNo(rowNo);
       try {
         ex.setColumn(getColumnName(colNo));
       } catch (DataStoreException e) {
       }
       ;
       v.add(ex);
     }
   }
   if (remoteRules) {
     try {
       DataStoreRow r = getDataStoreRow(rowNo, BUFFER_STANDARD);
       r.getDSDataRow().setProxyRow(rowNo);
       DataStoreException ex[] = getDataSourceProxy().validateRemoteRules(this, r, rowNo, colNo);
       for (int i = 0; i < ex.length; i++) v.add(ex[i]);
     } catch (DataStoreException dex) {
     }
   }
 }
  /**
   * The run method for the thread that retrieves the data from the database. This method should not
   * be called directly. Instead use the retrieve method.
   */
  public void run() {
    try {
      DataStoreRow row = new DataStoreRow(this, new DSDataRow(_desc), _desc);

      while (_dataSource.retrieveRow(this, row)) {
        _rows.addElement(row.getDSDataRow());
        if (_threaded) notifyListeners(ModelChangedEvent.TYPE_ROW_INSERTED_OR_DELETED);

        if (!_retrieveInProgress || (_maxRows > -1 && _rows.size() >= _maxRows)) {
          _cancelInProgress = true;
          _retrieveInProgress = false;
          interruptWaitingRetrieveThreads();
          break;
        }
        if (_threaded) Thread.yield();

        row.setDSDataRow(new DSDataRow(_desc));
      }
      _dataSource.postRetrieve(this);
      _cancelInProgress = false;
      interruptWaitingCancelThreads();
      notifyListeners(ModelChangedEvent.TYPE_DATA_LOADED);
    } catch (Exception e) {
      System.out.println("DataStore.run:" + e);
      _cancelInProgress = false;
      interruptWaitingCancelThreads();
    }

    _retrieveInProgress = false;
    interruptWaitingRetrieveThreads();
    _cancelInProgress = false;
    interruptWaitingCancelThreads();
  }
  void updateDs(DSDataSourceProxy out) throws DataStoreException, java.sql.SQLException, Exception {
    int rowNo = -1;
    DataStoreRow row = new DataStoreRow(this, null, _desc);

    // do deletes
    for (rowNo = 0; rowNo < _deletedRows.size(); rowNo++) {
      row.setDSDataRow((DSDataRow) _deletedRows.elementAt(rowNo));
      ((DSDataRow) _deletedRows.elementAt(rowNo)).setProxyRow(rowNo);
      if (!out.deleteRow(this, row)) throw new Exception("$Delete$");
    }

    // do the updates
    for (rowNo = 0; rowNo < _rows.size(); rowNo++) {
      row.setDSDataRow((DSDataRow) _rows.elementAt(rowNo));
      ((DSDataRow) _rows.elementAt(rowNo)).setProxyRow(rowNo);
      if (row.getDSDataRow().getRowStatus() == STATUS_MODIFIED) {
        if (!out.updateRow(this, row)) throw new Exception("$Update$");
      }
    }

    // do the inserts
    for (rowNo = 0; rowNo < _rows.size(); rowNo++) {
      row.setDSDataRow((DSDataRow) _rows.elementAt(rowNo));
      ((DSDataRow) _rows.elementAt(rowNo)).setProxyRow(rowNo);
      if (row.getDSDataRow().getRowStatus() == STATUS_NEW_MODIFIED) {
        if (!out.insertRow(this, row)) throw new Exception("$Insert$");
      }
    }
  }