function rows = execute(conn, query, varargin)
  % execute the given SQL query with optional parameters varargin
  % through connection conn. the results are returned in a 2d cell
  % array
  %
  % differs from similar riutines in utils.jmysql by the use of proper
  % SQL escaping of the query arguments. the connection object should
  % be an object implementing the java.sql.Connection interface.

  if nargin < 2
    error('### incorrect usage');
  end
  if ~isjava(conn)
    error('### invalid connection');
  end

  % return value
  rows = {};

  % build query
  stmt = conn.prepareStatement(query);
  for kk = 1:numel(varargin)
    stmt.setObject(kk, varargin{kk});
  end

  % execute query
  rs = stmt.executeQuery();

  % get results into a cell array
  ncols = rs.getMetaData.getColumnCount();
  row = 1;
  while rs.next()
    for kk = 1:ncols
      rows{row,kk} = java2matlab(rs.getObject(kk));
    end
    row = row + 1;
  end

end

function val = java2matlab(val)
  % matlab converts all base types. just add a conversion for datetime columns
  switch class(val)
    case 'java.sql.Timestamp'
      val = time(plist('time', char(val), 'timezone', 'UTC'));
  end
end
