//-------------------------------------------------------
        // Record traversal methods
        //-------------------------------------------------------

        /// <summary>
        /// Retrieve next record. Returns true if record exists and false if no more
        /// records are available.
        /// This method will block until a record is retrieved or the query is cancelled.
        /// </summary>
        public bool Next()
        {
            if (!valid)
            {
                executor.CheckForException();
                return(false);
            }

            try
            {
                record = queue.Take(cancelToken);
            }
            catch (OperationCanceledException)
            {
                valid = false;
                executor.CheckForException();
                return(false);
            }

            if (record == END)
            {
                valid = false;
                executor.CheckForException();
                return(false);
            }
            return(true);
        }
        //-------------------------------------------------------
        // Methods for internal use only.
        //-------------------------------------------------------

        /// <summary>
        /// Put a record on the queue.
        /// </summary>
        public bool Put(KeyRecord record)
        {
            if (!valid)
            {
                return(false);
            }

            try
            {
                // This add will block if queue capacity is reached.
                queue.Add(record, cancelToken);
                return(true);
            }
            catch (OperationCanceledException)
            {
                // Valid may have changed.  Check again.
                if (valid)
                {
                    Abort();
                }
                return(false);
            }
        }
        //-------------------------------------------------------
        // Record traversal methods
        //-------------------------------------------------------
        /// <summary>
        /// Retrieve next record. Returns true if record exists and false if no more 
        /// records are available.
        /// This method will block until a record is retrieved or the query is cancelled.
        /// </summary>
        public bool Next()
        {
            if (!valid)
            {
                executor.CheckForException();
                return false;
            }

            try
            {
                record = queue.Take(cancelToken);
            }
            catch (OperationCanceledException)
            {
                valid = false;
                executor.CheckForException();
                return false;
            }

            if (record == END)
            {
                valid = false;
                executor.CheckForException();
                return false;
            }
            return true;
        }
        //-------------------------------------------------------
        // Methods for internal use only.
        //-------------------------------------------------------
        /// <summary>
        /// Put a record on the queue.
        /// </summary>
        public bool Put(KeyRecord record)
        {
            if (!valid)
            {
                return false;
            }

            try
            {
                // This add will block if queue capacity is reached.
                queue.Add(record, cancelToken);
                return true;
            }
            catch (OperationCanceledException)
            {
                // Valid may have changed.  Check again.
                if (valid)
                {
                    Abort();
                }
                return false;
            }
        }
        public KeyRecordEnumerator Select(Statement stmt, bool metaOnly, params Qualifier[] qualifiers)
        {
            KeyRecordEnumerator results = null;
            /*
             * no filters
             */
            if (qualifiers == null || qualifiers.Length == 0)  {
                RecordSet recordSet = this.client.Query(null, stmt);
                results = new KeyRecordEnumerator(stmt.Namespace, recordSet);
                return results;
            }
            /*
             * singleton using primary key
             */
            if (qualifiers != null && qualifiers.Length == 1 && qualifiers[0] is KeyQualifier)  {
                KeyQualifier kq = (KeyQualifier)qualifiers[0];
                Key key = kq.MakeKey(stmt.Namespace, stmt.SetName);
                //System.out.println(key);
                Record record = null;
                if (metaOnly)
                    record = this.client.GetHeader(null, key);
                else
                    record = this.client.Get(null, key, stmt.BinNames);
                if (record == null){
                    results = new KeyRecordEnumerator(stmt.Namespace);
                } else {
                    KeyRecord keyRecord = new KeyRecord(key, record);
                    results = new KeyRecordEnumerator(stmt.Namespace, keyRecord);
                }
                return results;
            }
            /*
             *  query with filters
             */
            Dictionary<String, Object> originArgs = new Dictionary<String, Object>();
            originArgs["includeAllFields"] = 1;

            for (int i = 0; i < qualifiers.Length; i++){
                Qualifier qualifier = qualifiers[i];
                if (isIndexedBin(qualifier)){
                    Filter filter = qualifier.AsFilter();
                    if (filter != null){
                        stmt.Filters = new Filter[] { filter };
                        qualifiers[i] = null;
                        break;
                    }
                }
            }

            String filterFuncStr = buildFilterFunction(qualifiers);
            originArgs["filterFuncStr"] = filterFuncStr;
            Value argValue = Value.Get (originArgs);
            String fnName = "";

            if (metaOnly)
                fnName = "query_meta";
            else
                fnName = "select_records";

            stmt.SetAggregateFunction(
                Assembly.GetExecutingAssembly(),
                "Aerospike.Helper.udf."+ QUERY_MODULE + ".lua",
                QUERY_MODULE,
                fnName,
                argValue);

            ResultSet resultSet = this.client.QueryAggregate(null, stmt);
            results = new KeyRecordEnumerator(stmt.Namespace, resultSet);
            return results;
        }