All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sequoiadb.base.DBCollection Maven / Gradle / Ivy

There is a newer version: 5.10
Show newest version
/*
 * Copyright 2018 SequoiaDB Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.sequoiadb.base;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.bson.BSONObject;
import org.bson.BasicBSONObject;
import org.bson.types.BasicBSONList;
import org.bson.types.ObjectId;
import org.bson.util.JSON;

import com.sequoiadb.exception.BaseException;
import com.sequoiadb.exception.SDBError;
import com.sequoiadb.message.ResultSet;
import com.sequoiadb.message.request.AdminRequest;
import com.sequoiadb.message.request.AggregateRequest;
import com.sequoiadb.message.request.DeleteRequest;
import com.sequoiadb.message.request.InsertRequest;
import com.sequoiadb.message.request.LobCreateIDRequest;
import com.sequoiadb.message.request.LobRemoveRequest;
import com.sequoiadb.message.request.LobTruncateRequest;
import com.sequoiadb.message.request.QueryRequest;
import com.sequoiadb.message.request.UpdateRequest;
import com.sequoiadb.message.response.SdbReply;

/**
 * Collection of SequoiaDB.
 */
public class DBCollection {
    private String name;
    private Sequoiadb sequoiadb;
    private CollectionSpace collectionSpace;
    private String csName;
    private String collectionFullName;
    private Set mainKeys;
    private boolean ensureOID;

    private boolean isOldLobServer = true;

    /**
     * The flag represent whether insert continue(no errors were reported) when hitting index key
     * duplicate error
     */
    public static final int FLG_INSERT_CONTONDUP = 0x00000001;

    /**
     * The flag represent whether insert return the "_id" field of the record for user
     */
    public static final int FLG_INSERT_RETURN_OID = 0x10000000;

    /**
     * The flag represent whether insert becomes update when hitting index key duplicate error.
     */
    public static final int FLG_INSERT_REPLACEONDUP = 0x00000004;

    /**
     * The sharding key in update rule is not filtered, when executing update or upsert.
     */
    public static final int FLG_UPDATE_KEEP_SHARDINGKEY = 0x00008000;

    /**
     * The flag represent whether to update only one matched record or all matched records.
     */
    public static final int FLG_UPDATE_ONE = 0x00000002;

    /**
     * The flag represent whether to delete only one matched record or all matched records
     */
    public static final int FLG_DELETE_ONE = 0x00000002;

    /**
     * Get the name of current collection.
     *
     * @return The collection name
     */
    public String getName() {
        return name;
    }

    /**
     * Get the full name of specified collection in current collection space.
     *
     * @return The full name of specified collection
     */
    public String getFullName() {
        return collectionFullName;
    }

    /**
     * Get the full name of specified collection in current collection space.
     *
     * @return The full name of specified collection.
     */
    public String getCSName() {
        return csName;
    }

    /**
     * Get the Sequoiadb instance of current collection.
     *
     * @return Sequoiadb instance
     */
    public Sequoiadb getSequoiadb() {
        return sequoiadb;
    }

    /**
     * Get the CollectionSpace instance of current collection.
     *
     * @return CollectionSpace instance
     */
    public CollectionSpace getCollectionSpace() {
        return collectionSpace;
    }

    /**
     * Set the main keys used in save(). if no main keys are set, use the default main key "_id".
     * Every time invokes this method, it will remove the main keys set in the last time.
     *
     * @param keys the main keys specified by user. the main key should exist in the object
     * @throws BaseException when keys is null
     */
    public void setMainKeys(String[] keys) throws BaseException {
        if (keys == null) {
            throw new BaseException(SDBError.SDB_INVALIDARG, "keys is null");
        }
        // remove the main keys set in the last time
        mainKeys.clear();

        // add the new main keys
        if (keys.length == 0) {
            return;
        }

        for (String k : keys) {
            mainKeys.add(k);
        }
    }

    /**
     * @param sequoiadb Sequoiadb object
     * @param cs        CollectionSpace object
     * @param name      Collection name
     */
    DBCollection(Sequoiadb sequoiadb, CollectionSpace cs, String name) {
        this.name = name;
        this.sequoiadb = sequoiadb;
        this.collectionSpace = cs;
        this.csName = cs.getName();
        this.collectionFullName = csName + "." + name;
        this.mainKeys = new HashSet();
        this.ensureOID = true;
    }

    /**
     * Insert a document into current collection.
     *
     * @param insertor The bson object to be inserted, can't be null.
     * @param flags    The flag to control the behavior of inserting. The value of flags default to be 0,
     *                 and it can choose the follow values:
     *                 
    *
  • 0: default value.
  • *
  • FLG_INSERT_CONTONDUP: if the record hit index key duplicate error, database * will skip them and go on inserting.
  • *
  • FLG_INSERT_RETURN_OID: return the value of "_id" field in the record.
  • *
  • FLG_INSERT_REPLACEONDUP: if the record hit index key duplicate error, database * will replace the existing record by the inserting new record.
  • *
* @return The result of inserting, can be the follow values: *
    *
  • null: when there is no result to return.
  • *
  • bson which contains the "_id" field: when flag "FLG_INSERT_RETURN_OID" is set, * return the value of "_id" field of the inserted record. e.g.: { "_id": { "$oid": * "5c456e8eb17ab30cfbf1d5d1" } }
  • *
* @throws BaseException If error happens. */ public BSONObject insert(BSONObject insertor, int flags) throws BaseException { BSONObject result = null; if (insertor == null) { throw new BaseException(SDBError.SDB_INVALIDARG); } // send to engine InsertRequest request = new InsertRequest(collectionFullName, insertor, flags); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, insertor); sequoiadb.upsertCache(collectionFullName); // return result if ((flags & FLG_INSERT_RETURN_OID) != 0) { Object oid = request.getOIDValue(); if (oid != null) { result = new BasicBSONObject(); result.put(SdbConstants.OID, oid); } } return result; } /** * Insert a document into current collection, if the document does not contain field "_id", it * will be added. * * @param insertor The insertor. * @return the value of the filed "_id" * @throws BaseException If error happens. */ public Object insert(BSONObject insertor) throws BaseException { BSONObject result = insert(insertor, FLG_INSERT_RETURN_OID); return result.get(SdbConstants.OID); } /** * Insert a document into current collection, if the document does not contain field "_id", it * will be added. * * @param insertor The string of insertor * @return the value of the filed "_id" * @throws BaseException If error happens. */ public Object insert(String insertor) throws BaseException { BSONObject in = null; if (insertor != null) { in = (BSONObject) JSON.parse(insertor); } return insert(in); } /** * Insert a bulk of bson objects into current collection. * * @param insertor The Bson object of insertor list, can't be null * @param flags The flag to control the behavior of inserting. The value of flags default to be 0, * and it can choose the follow values: *
    *
  • 0: default value.
  • *
  • FLG_INSERT_CONTONDUP: if the record hit index key duplicate error, database * will skip them and go on inserting.
  • *
  • FLG_INSERT_RETURN_OID: return the value of "_id" field in the record. When set * this flag, ensureOID() will be set to true.
  • *
  • FLG_INSERT_REPLACEONDUP: if the record hit index key duplicate error, database * will replace the existing record by the inserting new record and them go on * inserting.
  • *
* @return The result of inserting, can be the follow values: *
    *
  • null: when there is no result to return.
  • *
  • bson which contains the "_id" field: when flag "FLG_INSERT_RETURN_OID" is set, * return all the values of "_id" field in a bson array. e.g.: { "_id": [ { "$oid": * "5c456e8eb17ab30cfbf1d5d1" }, { "$oid": "5c456e8eb17ab30cfbf1d5d2" } ] }
  • *
* @throws BaseException If error happens. * @since 3.0.2 */ public BSONObject insertRecords(List insertor, int flags) throws BaseException { BSONObject result = null; if (insertor == null || insertor.size() == 0) { throw new BaseException(SDBError.SDB_INVALIDARG); } // try to ensure oid if ((flags & FLG_INSERT_RETURN_OID) != 0) { if (!isOIDEnsured()) { ensureOID(true); } } // build and send message InsertRequest request = new InsertRequest(collectionFullName, insertor, flags, ensureOID); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response); sequoiadb.upsertCache(collectionFullName); // return result if ((flags & FLG_INSERT_RETURN_OID) != 0) { Object oid = request.getOIDValue(); if (oid != null) { result = new BasicBSONObject(); result.put(SdbConstants.OID, oid); } } sequoiadb.cleanRequestBuff(); return result; } /** * Insert a bulk of bson objects into current collection. * * @param insertor The Bson object of insertor list, can't be null * @param flags The flag to control the behavior of inserting. The value of flags default to be 0, * and it can choose the follow values: *
    *
  • 0: default value
  • *
  • FLG_INSERT_CONTONDUP: if the record hit index key duplicate error, database * will skip them and go on inserting.
  • *
  • FLG_INSERT_REPLACEONDUP: if the record hit index key duplicate error, database * will replace the existing record by the inserting new record and them go on * inserting.
  • *
* @throws BaseException If error happens. * @since 3.0.2 */ public void insert(List insertor, int flags) throws BaseException { if (flags != 0) { flags = DBQuery.eraseSingleFlag(flags, FLG_INSERT_RETURN_OID); } insertRecords(insertor, flags); } /** * Insert a bulk of bson objects into current collection. * * @param insertor The Bson object of insertor list, can't be null. insert will interrupt when * Duplicate key exist. * @throws BaseException If error happens. * @since 2.9 */ public void insert(List insertor) throws BaseException { insert(insertor, 0); } /** * Insert an object into current collection. When flag is set to 0, it won't work to update the * ShardingKey field, but the other fields take effect. * * @param type The object of insertor, can't be null * @param ignoreNullValue true:if type's inner value is null, it will not save to collection; * @param flag the update flag, default to be 0. Please see the definition of follow flags for * more detail. *
    *
  • DBCollection.FLG_UPDATE_KEEP_SHARDINGKEY *
* @throws BaseException 1.when the type is not support, throw BaseException with the type * "SDB_INVALIDARG" 2.when offer main keys by setMainKeys(), and try to update "_id" * field, it may get a BaseException with the type of "SDB_IXM_DUP_KEY" * @see com.sequoiadb.base.DBCollection#setMainKeys(String[]) */ public /* ! @cond x */ /* ! @endcond */ void save(T type, Boolean ignoreNullValue, int flag) throws BaseException { // transform java object to bson object BSONObject obj; try { obj = BasicBSONObject.typeToBson(type, ignoreNullValue); } catch (Exception e) { throw new BaseException(SDBError.SDB_INVALIDARG, type.toString(), e); } BSONObject matcher = new BasicBSONObject(); BSONObject modifer = new BasicBSONObject(); // if user don't specify main keys, use default one "_id" if (mainKeys.isEmpty()) { Object id = obj.get(SdbConstants.OID); if (id == null || (id instanceof ObjectId && ((ObjectId) id).isNew())) { if (id != null && id instanceof ObjectId) { ((ObjectId) id).notNew(); } insert(obj); } else { // build condtion matcher.put(SdbConstants.OID, id); // build rule modifer.put("$set", obj); upsert(matcher, modifer, null, null, flag); } } else { // if user specify main keys, use these main keys Iterator it = mainKeys.iterator(); // build condition while (it.hasNext()) { String key = it.next(); if (obj.containsField(key)) { matcher.put(key, obj.get(key)); } } // build rule if (!matcher.isEmpty()) { modifer.put("$set", obj); upsert(matcher, modifer, null, null, flag); } else { insert(obj); } } } /** * Insert an object into current collection when save include update shardingKey field, the * shardingKey modify action is not take effect, but the other field update is take effect. * * @param type The object of insertor, can't be null * @param ignoreNullValue true:if type's inner value is null, it will not save to collection; false:if * type's inner value is null, it will save to collection too. * @throws BaseException 1.when the type is not support, throw BaseException with the type * "SDB_INVALIDARG" 2.when offer main keys by setMainKeys(), and try to update "_id" * field, it may get a BaseException with the type of "SDB_IXM_DUP_KEY" * @see com.sequoiadb.base.DBCollection#setMainKeys(String[]) */ public /* ! @cond x */ /* ! @endcond */ void save(T type, Boolean ignoreNullValue) throws BaseException { save(type, ignoreNullValue, 0); } /** * Insert an object into current collection. when save include update shardingKey field, the * shardingKey modify action is not take effect, but the other field update is take effect. * * @param type The object of insertor, can't be null * @throws BaseException 1.when the type is not support, throw BaseException with the type * "SDB_INVALIDARG" 2.when offer main keys by setMainKeys(), and try to update "_id" * field, it may get a BaseException with the type of "SDB_IXM_DUP_KEY" * @see com.sequoiadb.base.DBCollection#setMainKeys(String[]) */ public /* ! @cond x */ /* ! @endcond */ void save(T type) throws BaseException { save(type, false); } /** * Insert an object into current collection. When flag is set to 0, it won't work to update the * ShardingKey field, but the other fields take effect. * * @param type The List instance of insertor, can't be null or empty * @param ignoreNullValue true:if type's inner value is null, it will not save to collection; * @param flag the update flag, default to be 0. Please see the definition of follow flags for * more detail. *
    *
  • DBCollection.FLG_UPDATE_KEEP_SHARDINGKEY *
* @throws BaseException 1.while the input argument is null or the List instance is empty 2.while the type * is not support, throw BaseException with the type "SDB_INVALIDARG" 3.while offer * main keys by setMainKeys(), and try to update "_id" field, it may get a * BaseException with the type of "SDB_IXM_DUP_KEY" when the "_id" field you want to * update to had been existing in database * @see com.sequoiadb.base.DBCollection#setMainKeys(String[]) */ public /* ! @cond x */ /* ! @endcond */ void save(List type, Boolean ignoreNullValue, int flag) throws BaseException { if (type == null || type.size() == 0) { throw new BaseException(SDBError.SDB_INVALIDARG, "type is empty or null"); } // transform java object to bson object List objs = new ArrayList(); try { Iterator it = type.iterator(); while (it != null && it.hasNext()) { objs.add(BasicBSONObject.typeToBson(it.next(), ignoreNullValue)); } } catch (Exception e) { throw new BaseException(SDBError.SDB_INVALIDARG, type.toString(), e); } BSONObject matcher = new BasicBSONObject(); BSONObject modifer = new BasicBSONObject(); BSONObject obj = null; Iterator ite = objs.iterator(); // if user don't specify main keys, use default one "_id" if (mainKeys.isEmpty()) { while (ite != null && ite.hasNext()) { obj = ite.next(); Object id = obj.get(SdbConstants.OID); if (id == null || (id instanceof ObjectId && ((ObjectId) id).isNew())) { if (id != null && id instanceof ObjectId) { ((ObjectId) id).notNew(); } insert(obj); } else { // build condtion matcher.put(SdbConstants.OID, id); // build rule modifer.put("$set", obj); upsert(matcher, modifer, null, null, flag); } } } else { // if user specify main keys, use these main keys while (ite != null && ite.hasNext()) { obj = ite.next(); Iterator i = mainKeys.iterator(); // build condition while (i.hasNext()) { String key = i.next(); if (obj.containsField(key)) { matcher.put(key, obj.get(key)); } } if (!matcher.isEmpty()) { // build rule modifer.put("$set", obj); upsert(matcher, modifer, null, null, flag); } else { insert(obj); } } } } /** * Insert an object into current collection. when save include update shardingKey field, the * shardingKey modify action is not take effect, but the other field update is take effect. * * @param type The List instance of insertor, can't be null or empty * @param ignoreNullValue true:if type's inner value is null, it will not save to collection; false:if * type's inner value is null, it will save to collection too. * @throws BaseException 1.while the input argument is null or the List instance is empty 2.while the type * is not support, throw BaseException with the type "SDB_INVALIDARG" 3.while offer * main keys by setMainKeys(), and try to update "_id" field, it may get a * BaseException with the type of "SDB_IXM_DUP_KEY" when the "_id" field you want to * update to had been existing in database * @see com.sequoiadb.base.DBCollection#setMainKeys(String[]) */ public /* ! @cond x */ /* ! @endcond */ void save(List type, Boolean ignoreNullValue) throws BaseException { save(type, ignoreNullValue, 0); } /** * Insert an object into current collection. when save include update shardingKey field, the * shardingKey modify action is not take effect, but the other field update is take effect. * * @param type The List instance of insertor, can't be null or empty * @throws BaseException 1.while the input argument is null or the List instance is empty 2.while the type * is not support, throw BaseException with the type "SDB_INVALIDARG" 3.while offer * main keys by setMainKeys(), and try to update "_id" field, it may get a * BaseException with the type of "SDB_IXM_DUP_KEY" when the "_id" field you want to * update to had been existing in database * @see com.sequoiadb.base.DBCollection#setMainKeys(String[]) */ public /* ! @cond x */ /* ! @endcond */ void save(List type) throws BaseException { save(type, false); } /** * Set whether ensure OID of record when bulk insert records to SequoiaDB. * * @param flag whether ensure OID of record */ public void ensureOID(boolean flag) { ensureOID = flag; } /** * @return True if ensure OID of record when bulk insert records to SequoiaDB and false if not. */ public boolean isOIDEnsured() { return ensureOID; } /** * Insert a bulk of bson objects into current collection. * * @param insertor The Bson object of insertor list, can't be null * @param flags The flag to control the behavior of inserting. The value of flags default to be 0, * and it can choose the follow values: *
    *
  • 0: default value
  • *
  • FLG_INSERT_CONTONDUP: if the record hit index key duplicate error, database * will skip them and go on inserting.
  • *
  • FLG_INSERT_REPLACEONDUP: if the record hit index key duplicate error, database * will replace the existing record by the inserting new record and them go on * inserting.
  • *
* @throws BaseException If error happens. * @deprecated use insert(List insertor, int flags) instead */ @Deprecated public void bulkInsert(List insertor, int flags) throws BaseException { insert(insertor, flags); } /** * Delete the matching records of current collection. * * @param matcher The matching condition, match all the documents if null * @throws BaseException If error happens. */ public void delete(BSONObject matcher) throws BaseException { delete(matcher, null); } /** * Delete the matching records of current collection. * * @param matcher The matching condition, match all the documents if null * @throws BaseException If error happens. */ public void delete(String matcher) throws BaseException { BSONObject ma = null; if (matcher != null) { ma = (BSONObject) JSON.parse(matcher); } delete(ma, null); } /** * Delete the matching records of current collection. * * @param matcher The matching condition, match all the documents if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @throws BaseException If error happens. */ public void delete(String matcher, String hint) throws BaseException { BSONObject ma = null; BSONObject hi = null; if (matcher != null) { ma = (BSONObject) JSON.parse(matcher); } if (hint != null) { hi = (BSONObject) JSON.parse(hint); } delete(ma, hi, 0); } /** * Delete the matching records of current collection. * * @param matcher The matching condition, match all the documents if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @throws BaseException If error happens. */ public void delete(BSONObject matcher, BSONObject hint) throws BaseException { delete(matcher, hint, 0); } /** * Delete the matching records of current collection. * * @param matcher The matching condition, match all the documents if null. * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param flag The delete flag, default to be 0. *
    *
  • {@link DBCollection#FLG_DELETE_ONE} *
* @throws BaseException If error happens. */ public void delete(BSONObject matcher, BSONObject hint, int flag) throws BaseException { DeleteRequest request = new DeleteRequest(collectionFullName, matcher, hint, flag); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "matcher = " + matcher + ", hint = " + hint; sequoiadb.throwIfError(response, msg); } sequoiadb.upsertCache(collectionFullName); } /** * Update the matching records of current collection. It won't work to update the ShardingKey field, but * the other fields take effect. * * @param query DBQuery with matching condition, updating rule and hint * @throws BaseException If error happens. */ public void update(DBQuery query) throws BaseException { _update(query.getFlag(), query.getMatcher(), query.getModifier(), query.getHint()); } /** * Update the matching records of current collection. It won't work to update the ShardingKey field, * but the other fields take effect. * * @param matcher The matching condition, match all the documents if null * @param modifier The updating rule, can't be null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @throws BaseException If error happens. */ public void update(BSONObject matcher, BSONObject modifier, BSONObject hint) throws BaseException { _update(0, matcher, modifier, hint); } /** * Update the matching records of current collection. When flag is set to 0, it won't work to update * the ShardingKey field, but the other fields take effect. * * @param matcher The matching condition, match all the documents if null * @param modifier The updating rule, can't be null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param flag the update flag, default to be 0. Please see the definition of follow flags for * more detail. *
    *
  • {@link DBCollection#FLG_UPDATE_KEEP_SHARDINGKEY} *
  • {@link DBCollection#FLG_UPDATE_ONE} *
* @throws BaseException If error happens. */ public void update(BSONObject matcher, BSONObject modifier, BSONObject hint, int flag) throws BaseException { _update(flag, matcher, modifier, hint); } /** * Update the matching records of current collection. It won't work to update the ShardingKey field, * but the other fields take effect. * * @param matcher The matching condition, match all the documents if null * @param modifier The updating rule, can't be null or empty * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @throws BaseException If error happens. */ public void update(String matcher, String modifier, String hint) throws BaseException { BSONObject ma = null; BSONObject mo = null; BSONObject hi = null; if (matcher != null) { ma = (BSONObject) JSON.parse(matcher); } if (modifier != null) { mo = (BSONObject) JSON.parse(modifier); } if (hint != null) { hi = (BSONObject) JSON.parse(hint); } _update(0, ma, mo, hi); } /** * Update the matching records of current collection. When flag is set to 0, it won't work to update * the ShardingKey field, but the other fields take effect. * * @param matcher The matching condition, match all the documents if null * @param modifier The updating rule, can't be null or empty * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param flag the update flag, default to be 0. Please see the definition of follow flags for * more detail. *
    *
  • {@link DBCollection#FLG_UPDATE_KEEP_SHARDINGKEY} *
  • {@link DBCollection#FLG_UPDATE_ONE} *
* @throws BaseException If error happens. */ public void update(String matcher, String modifier, String hint, int flag) throws BaseException { BSONObject ma = null; BSONObject mo = null; BSONObject hi = null; if (matcher != null) { ma = (BSONObject) JSON.parse(matcher); } if (modifier != null) { mo = (BSONObject) JSON.parse(modifier); } if (hint != null) { hi = (BSONObject) JSON.parse(hint); } _update(flag, ma, mo, hi); } /** * Update the matching records of current collection, insert if no matching. It won't work to update * the ShardingKey field, but the other fields take effect. * * @param matcher The matching condition, match all the documents if null * @param modifier The updating rule, can't be null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @throws BaseException If error happens. */ public void upsert(BSONObject matcher, BSONObject modifier, BSONObject hint) throws BaseException { _update(SdbConstants.FLG_UPDATE_UPSERT, matcher, modifier, hint); } /** * Update the matching records of current collection, insert if no matching. It won't work to update * the ShardingKey field, but the other fields take effect. * * @param matcher The matching condition, match all the documents if null * @param modifier The updating rule, can't be null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param setOnInsert When "setOnInsert" is not a null or an empty object, it assigns the specified * values to the fields when insert. * @throws BaseException If error happens. */ public void upsert(BSONObject matcher, BSONObject modifier, BSONObject hint, BSONObject setOnInsert) throws BaseException { upsert(matcher, modifier, hint, setOnInsert, 0); } /** * Update the matching records of current collection, insert if no matching. When flag is set to 0, it * won't work to update the ShardingKey field, but the other fields take effect. * * @param matcher The matching condition, match all the documents if null * @param modifier The updating rule, can't be null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param setOnInsert When "setOnInsert" is not a null or an empty object, it assigns the specified * values to the fields when insert. * @param flag the upsert flag, default to be 0. Please see the definition of follow flags for * more detail. *
    *
  • {@link DBCollection#FLG_UPDATE_KEEP_SHARDINGKEY} *
  • {@link DBCollection#FLG_UPDATE_ONE} *
* @throws BaseException If error happens. */ public void upsert(BSONObject matcher, BSONObject modifier, BSONObject hint, BSONObject setOnInsert, int flag) throws BaseException { BSONObject newHint; if (setOnInsert != null) { newHint = new BasicBSONObject(); if (hint != null) { newHint.putAll(hint); } newHint.put(SdbConstants.FIELD_NAME_SET_ON_INSERT, setOnInsert); } else { newHint = hint; } flag |= SdbConstants.FLG_UPDATE_UPSERT; _update(flag, matcher, modifier, newHint); } /** * Explain query of current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param skipRows skip the first numToSkip documents, never skip if this parameter is 0 * @param returnRows return the specified amount of documents, when returnRows is 0, return nothing, * when returnRows is -1, return all the documents * @param flag the query flag, default to be 0. Please see the definition of follow flags for * more detail. Usage: e.g. set ( DBQuery.FLG_QUERY_FORCE_HINT | * DBQuery.FLG_QUERY_WITH_RETURNDATA ) to param flag *
    *
  • DBQuery.FLG_QUERY_STRINGOUT *
  • DBQuery.FLG_QUERY_FORCE_HINT *
  • DBQuery.FLG_QUERY_PARALLED *
  • DBQuery.FLG_QUERY_WITH_RETURNDATA *
* @param options The rules of query explain, the options are as below: *
    *
  • Run : Whether execute query explain or not, true for executing query explain * then get the data and time information; false for not executing query explain but * get the query explain information only. e.g. {Run:true} *
* @return a DBCursor instance of the result * @throws BaseException If error happens. */ public DBCursor explain(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows, int flag, BSONObject options) throws BaseException { BSONObject innerHint = new BasicBSONObject(); if (hint != null) { innerHint.put(SdbConstants.FIELD_NAME_HINT, hint); } if (options != null) { innerHint.put(SdbConstants.FIELD_NAME_OPTIONS, options); } if (flag != 0) { flag = DBQuery.eraseSingleFlag(flag, DBQuery.FLG_QUERY_MODIFY); } flag |= DBQuery.FLG_QUERY_EXPLAIN; return _query(matcher, selector, orderBy, innerHint, skipRows, returnRows, flag); } /** * Get all documents of current collection. * * @return a DBCursor instance of the result * @throws BaseException If error happens. */ public DBCursor query() throws BaseException { return query("", "", "", "", 0, -1); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. * @see com.sequoiadb.base.DBQuery */ public DBCursor query(DBQuery matcher) throws BaseException { if (matcher == null) { return query(); } return query(matcher.getMatcher(), matcher.getSelector(), matcher.getOrderBy(), matcher.getHint(), matcher.getSkipRowsCount(), matcher.getReturnRowsCount(), matcher.getFlag()); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor query(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint) throws BaseException { return query(matcher, selector, orderBy, hint, 0, -1, 0); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param flag the query flag, default to be 0. Please see the definition of follow flags for * more detail. Usage: e.g. set ( DBQuery.FLG_QUERY_FORCE_HINT | * DBQuery.FLG_QUERY_WITH_RETURNDATA ) to param flag *
    *
  • DBQuery.FLG_QUERY_STRINGOUT *
  • DBQuery.FLG_QUERY_FORCE_HINT *
  • DBQuery.FLG_QUERY_PARALLED *
  • DBQuery.FLG_QUERY_WITH_RETURNDATA *
  • DBQuery.FLG_QUERY_FOR_UPDATE *
* @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor query(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, int flag) throws BaseException { return query(matcher, selector, orderBy, hint, 0, -1, flag); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor query(String matcher, String selector, String orderBy, String hint) throws BaseException { return query(matcher, selector, orderBy, hint, 0); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param flag the query flag, default to be 0. Please see the definition of follow flags for * more detail. Usage: e.g. set ( DBQuery.FLG_QUERY_FORCE_HINT | * DBQuery.FLG_QUERY_WITH_RETURNDATA ) to param flag *
    *
  • DBQuery.FLG_QUERY_STRINGOUT *
  • DBQuery.FLG_QUERY_FORCE_HINT *
  • DBQuery.FLG_QUERY_PARALLED *
  • DBQuery.FLG_QUERY_WITH_RETURNDATA *
  • DBQuery.FLG_QUERY_FOR_UPDATE *
* @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor query(String matcher, String selector, String orderBy, String hint, int flag) throws BaseException { BSONObject ma = null; BSONObject se = null; BSONObject or = null; BSONObject hi = null; if (matcher != null) { ma = (BSONObject) JSON.parse(matcher); } if (selector != null) { se = (BSONObject) JSON.parse(selector); } if (orderBy != null && !orderBy.equals("")) { or = (BSONObject) JSON.parse(orderBy); } if (hint != null) { hi = (BSONObject) JSON.parse(hint); } return query(ma, se, or, hi, 0, -1, flag); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param skipRows skip the first numToSkip documents, never skip if this parameter is 0 * @param returnRows return the specified amount of documents, when returnRows is 0, return nothing, * when returnRows is -1, return all the documents * @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor query(String matcher, String selector, String orderBy, String hint, long skipRows, long returnRows) throws BaseException { BSONObject ma = null; BSONObject se = null; BSONObject or = null; BSONObject hi = null; if (matcher != null) { ma = (BSONObject) JSON.parse(matcher); } if (selector != null) { se = (BSONObject) JSON.parse(selector); } if (orderBy != null) { or = (BSONObject) JSON.parse(orderBy); } if (hint != null) { hi = (BSONObject) JSON.parse(hint); } return query(ma, se, or, hi, skipRows, returnRows, 0); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param skipRows skip the first numToSkip documents, never skip if this parameter is 0 * @param returnRows return the specified amount of documents, when returnRows is 0, return nothing, * when returnRows is -1, return all the documents * @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor query(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows) throws BaseException { return query(matcher, selector, orderBy, hint, skipRows, returnRows, 0); } /** * Get the matching documents in current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param skipRows skip the first numToSkip documents, never skip if this parameter is 0 * @param returnRows return the specified amount of documents, when returnRows is 0, return nothing, * when returnRows is -1, return all the documents * @param flags the query flags, default to be 0. Please see the definition of follow flags for * more detail. Usage: e.g. set ( DBQuery.FLG_QUERY_FORCE_HINT | * DBQuery.FLG_QUERY_WITH_RETURNDATA ) to param flag *
    *
  • DBQuery.FLG_QUERY_STRINGOUT *
  • DBQuery.FLG_QUERY_FORCE_HINT *
  • DBQuery.FLG_QUERY_PARALLED *
  • DBQuery.FLG_QUERY_WITH_RETURNDATA *
  • DBQuery.FLG_QUERY_FOR_UPDATE *
* @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor query(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows, int flags) throws BaseException { if (flags != 0) { flags = DBQuery.eraseSingleFlag(flags, DBQuery.FLG_QUERY_EXPLAIN); flags = DBQuery.eraseSingleFlag(flags, DBQuery.FLG_QUERY_MODIFY); } return _query(matcher, selector, orderBy, hint, skipRows, returnRows, flags); } private DBCursor _query(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows, int flags) throws BaseException { int newFlags = DBQuery.regulateFlags(flags); if (returnRows < 0) { returnRows = -1; } if (returnRows == 1) { newFlags |= DBQuery.FLG_QUERY_WITH_RETURNDATA; } QueryRequest request = new QueryRequest(collectionFullName, matcher, selector, orderBy, hint, skipRows, returnRows, newFlags); SdbReply response = sequoiadb.requestAndResponse(request); int flag = response.getFlag(); if (flag != 0) { if (flag == SDBError.SDB_DMS_EOC.getErrorCode()) { return null; } else { String msg = "matcher = " + matcher + ", selector = " + selector + ", orderBy = " + orderBy + ", hint = " + hint + ", skipRows = " + skipRows + ", returnRows = " + returnRows + ", flags = " + flags; sequoiadb.throwIfError(response, msg); } } sequoiadb.upsertCache(collectionFullName); DBCursor cursor = new DBCursor(response, sequoiadb); return cursor; } /** * Get one matched document from current collection. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param flag the query flag, default to be 0. Please see the definition of follow flags for * more detail. Usage: e.g. set ( DBQuery.FLG_QUERY_FORCE_HINT | * DBQuery.FLG_QUERY_WITH_RETURNDATA ) to param flag *
    *
  • DBQuery.FLG_QUERY_STRINGOUT *
  • DBQuery.FLG_QUERY_FORCE_HINT *
  • DBQuery.FLG_QUERY_PARALLED *
  • DBQuery.FLG_QUERY_WITH_RETURNDATA *
  • DBQuery.FLG_QUERY_FOR_UPDATE *
* @return the matched document or null if no such document * @throws BaseException If error happens. */ public BSONObject queryOne(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, int flag) throws BaseException { flag = flag | DBQuery.FLG_QUERY_WITH_RETURNDATA; DBCursor cursor = query(matcher, selector, orderBy, hint, 0, 1, flag); BSONObject obj; try { obj = cursor.getNext(); } finally { cursor.close(); } return obj; } /** * Get one document from current collection. * * @return the document or null if no any document in current collection * @throws BaseException If error happens. */ public BSONObject queryOne() throws BaseException { return queryOne(null, null, null, null, 0); } /** * Get all the indexes of current collection * * @return DBCursor of indexes * @throws BaseException If error happens. */ public DBCursor getIndexes() throws BaseException { BSONObject obj = new BasicBSONObject(); obj.put(SdbConstants.FIELD_COLLECTION, collectionFullName); AdminRequest request = new AdminRequest(AdminCommand.GET_INDEXES, null, obj); SdbReply response = sequoiadb.requestAndResponse(request); int flags = response.getFlag(); if (flags != 0) { if (flags == SDBError.SDB_DMS_EOC.getErrorCode()) { return null; } else { sequoiadb.throwIfError(response); } } sequoiadb.upsertCache(collectionFullName); DBCursor cursor = new DBCursor(response, sequoiadb); return cursor; } private DBCursor _queryAndModify(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, BSONObject update, long skipRows, long returnRows, int flag, boolean isUpdate, boolean returnNew) throws BaseException { BSONObject modify = new BasicBSONObject(); if (isUpdate) { if (update == null || update.isEmpty()) { throw new BaseException(SDBError.SDB_INVALIDARG, "update can't be empty"); } modify.put(SdbConstants.FIELD_NAME_OP, SdbConstants.FIELD_OP_VALUE_UPDATE); modify.put(SdbConstants.FIELD_NAME_OP_UPDATE, update); modify.put(SdbConstants.FIELD_NAME_RETURNNEW, returnNew); } else { modify.put(SdbConstants.FIELD_NAME_OP, SdbConstants.FIELD_OP_VALUE_REMOVE); modify.put(SdbConstants.FIELD_NAME_OP_REMOVE, true); } BSONObject newHint = new BasicBSONObject(); if (hint != null) { newHint.putAll(hint); } newHint.put(SdbConstants.FIELD_NAME_MODIFY, modify); if (flag != 0) { flag = DBQuery.eraseSingleFlag(flag, DBQuery.FLG_QUERY_EXPLAIN); } flag |= DBQuery.FLG_QUERY_MODIFY; return _query(matcher, selector, orderBy, newHint, skipRows, returnRows, flag); } /** * Get the matching documents in current collection and update. In order to make the update take * effect, user must travel the DBCursor returned by this function. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param update the update rule, can't be null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param skipRows skip the first numToSkip documents, never skip if this parameter is 0 * @param returnRows return the specified amount of documents, when returnRows is 0, return nothing, * when returnRows is -1, return all the documents * @param flag the query flags, default to be 0. Please see the definition of follow flags for * more detail. Usage: e.g. set ( DBQuery.FLG_QUERY_FORCE_HINT | * DBQuery.FLG_QUERY_WITH_RETURNDATA ) to param flag *
    *
  • DBQuery.FLG_QUERY_STRINGOUT *
  • DBQuery.FLG_QUERY_FORCE_HINT *
  • DBQuery.FLG_QUERY_PARALLED *
  • DBQuery.FLG_QUERY_WITH_RETURNDATA *
  • DBQuery.FLG_QUERY_KEEP_SHARDINGKEY_IN_UPDATE *
  • DBQuery.FLG_QUERY_FOR_UPDATE *
* @param returnNew When true, returns the updated document rather than the original * @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor queryAndUpdate(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, BSONObject update, long skipRows, long returnRows, int flag, boolean returnNew) throws BaseException { return _queryAndModify(matcher, selector, orderBy, hint, update, skipRows, returnRows, flag, true, returnNew); } /** * Get the matching documents in current collection and remove. In order to make the remove take * effect, user must travel the DBCursor returned by this function. * * @param matcher the matching rule, return all the documents if null * @param selector the selective rule, return the whole document if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param skipRows skip the first numToSkip documents, never skip if this parameter is 0 * @param returnRows return the specified amount of documents, when returnRows is 0, return nothing, * when returnRows is -1, return all the documents * @param flag the query flag, default to be 0. Please see the definition of follow flags for * more detail. Usage: e.g. set ( DBQuery.FLG_QUERY_FORCE_HINT | * DBQuery.FLG_QUERY_WITH_RETURNDATA ) to param flag *
    *
  • DBQuery.FLG_QUERY_STRINGOUT *
  • DBQuery.FLG_QUERY_FORCE_HINT *
  • DBQuery.FLG_QUERY_PARALLED *
  • DBQuery.FLG_QUERY_WITH_RETURNDATA *
  • DBQuery.FLG_QUERY_FOR_UPDATE *
* @return a DBCursor instance of the result or null if no any matched document * @throws BaseException If error happens. */ public DBCursor queryAndRemove(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows, int flag) throws BaseException { return _queryAndModify(matcher, selector, orderBy, hint, null, skipRows, returnRows, flag, false, false); } /** * Get all of or one of the indexes in current collection. * * @param indexName The index indexName, returns all of the indexes if this parameter is null. * @return DBCursor of indexes. * @throws BaseException If error happens. * @deprecated use "getIndexInfo" or "getIndexes" API instead. */ @Deprecated public DBCursor getIndex(String indexName) throws BaseException { if (indexName == null) { return getIndexes(); } BSONObject condition = new BasicBSONObject(); condition.put(SdbConstants.IXM_INDEXDEF + "." + SdbConstants.IXM_NAME, indexName); BSONObject obj = new BasicBSONObject(); obj.put(SdbConstants.FIELD_COLLECTION, collectionFullName); AdminRequest request = new AdminRequest(AdminCommand.GET_INDEXES, condition, obj); SdbReply response = sequoiadb.requestAndResponse(request); int flags = response.getFlag(); if (flags != 0) { if (flags == SDBError.SDB_DMS_EOC.getErrorCode()) { return null; } else { sequoiadb.throwIfError(response); } } sequoiadb.upsertCache(collectionFullName); return new DBCursor(response, sequoiadb); } /** * Get the information of specified index in current collection. * * @param name The index name. * @return The information of the specified index. * @throws BaseException If error happens or the specified index does not exist. */ public BSONObject getIndexInfo(String name) throws BaseException { BSONObject retObj; if (name == null || name.isEmpty()) { throw new BaseException(SDBError.SDB_INVALIDARG, "index name can not be null or empty"); } BSONObject condition = new BasicBSONObject(); condition.put(SdbConstants.IXM_INDEXDEF + "." + SdbConstants.IXM_NAME, name); BSONObject obj = new BasicBSONObject(); obj.put(SdbConstants.FIELD_COLLECTION, collectionFullName); AdminRequest request = new AdminRequest(AdminCommand.GET_INDEXES, condition, obj); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { sequoiadb.throwIfError(response); } sequoiadb.upsertCache(collectionFullName); DBCursor cursor = new DBCursor(response, sequoiadb); try { if (cursor.hasNext()) { retObj = cursor.getNext(); return retObj; } else { throw new BaseException(SDBError.SDB_IXM_NOTEXIST, "the specified index[" + name + "] does not exist"); } } finally { cursor.close(); } } /** * Test the specified index exist or not. * * @param name The index name. * @return True for exist while false for not exist.. */ public boolean isIndexExist(String name) { if (name == null || name.isEmpty()) { return false; } BSONObject indexObj; try { indexObj = getIndexInfo(name); } catch (Exception e) { return false; } if (indexObj != null) { return true; } return false; } /** * Create a index with name and key. * * @param indexName The index name. * @param indexKeys The index keys in JSON format, like: { "a":1, "b":-1 }. * @param options Optional configuration, type is BSONObject. Please reference * {@see here} * for more detail, like: { "Unique" : false , "Enforced" : false , "NotNull" : false , "SortBufferSize" : 64 } * @throws BaseException */ public void createIndex(String indexName, BSONObject indexKeys, BSONObject options) throws BaseException { int sortBufferSize = 0; BSONObject matcher = new BasicBSONObject(); BSONObject hint = new BasicBSONObject(); BSONObject indexDef = new BasicBSONObject(); BSONObject indexOptions = new BasicBSONObject(); if (options != null) { indexOptions.putAll(options); } // we are going to build the below message: // matcher: { Collection: "foo.bar", // Index:{ key: {a:1}, name: 'aIdx', Unique: true, // Enforced: true, NotNull: true }, // SortBufferSize: 1024 } // hint: { SortBufferSize: 1024 } // For Compatibility with older engine( version <3.4 ), keep sort buffer // size in hint. After several versions, we can delete it. // prepare sortBufferSize if (indexOptions.containsField(SdbConstants.IXM_FIELD_NAME_SORT_BUFFER_SIZE)) { Object value = indexOptions.get(SdbConstants.IXM_FIELD_NAME_SORT_BUFFER_SIZE); if (value instanceof Integer) { sortBufferSize = (int)value; } else { throw new BaseException(SDBError.SDB_INVALIDARG, "sortBufferSize should be int value"); } indexOptions.removeField(SdbConstants.IXM_FIELD_NAME_SORT_BUFFER_SIZE); } else { sortBufferSize = SdbConstants.IXM_SORT_BUFFER_DEFAULT_SIZE; } // prepare indexDef indexDef.put(SdbConstants.IXM_NAME, indexName); indexDef.put(SdbConstants.IXM_KEY, indexKeys); indexDef.putAll(indexOptions); // build matcher matcher.put(SdbConstants.FIELD_COLLECTION, collectionFullName); matcher.put(SdbConstants.FIELD_INDEX, indexDef); matcher.put(SdbConstants.IXM_FIELD_NAME_SORT_BUFFER_SIZE, sortBufferSize); // build hint hint.put(SdbConstants.IXM_FIELD_NAME_SORT_BUFFER_SIZE, sortBufferSize); // build and send message AdminRequest request = new AdminRequest(AdminCommand.CREATE_INDEX, matcher, hint); SdbReply response = sequoiadb.requestAndResponse(request); // check return info if (response.getFlag() != 0) { String msg = "indexName = " + indexName + ", indexKeys = " + indexKeys.toString() + ", options = " + options.toString() + ", matcher = " + matcher.toString() + ", hint = " + hint.toString(); sequoiadb.throwIfError(response, msg); } sequoiadb.upsertCache(collectionFullName); } /** * Create a index with indexName and indexKeys. * * @param indexName The index indexName. * @param indexKeys The index keys in JSON format, like: { "a":1, "b":-1 }. * @param isUnique Whether the index elements are unique or not. * @param enforced Whether the index is enforced unique, this element is meaningful when isUnique is * set to true. * @param sortBufferSize The size(MB) of sort buffer used when creating index, zero means don't use sort * buffer. * @throws BaseException If error happens. */ public void createIndex(String indexName, BSONObject indexKeys, boolean isUnique, boolean enforced, int sortBufferSize) throws BaseException { BSONObject options = new BasicBSONObject(); options.put(SdbConstants.IXM_UNIQUE, isUnique); options.put(SdbConstants.IXM_ENFORCED, enforced); options.put(SdbConstants.IXM_FIELD_NAME_SORT_BUFFER_SIZE, sortBufferSize); createIndex(indexName, indexKeys, options); } /** * Create a index with indexName and indexKeys. * * @param indexName The index indexName. * @param indexKeys The index keys in JSON format, like: "{\"a\":1, \"b\":-1}". * @param isUnique Whether the index elements are unique or not. * @param enforced Whether the index is enforced unique, this element is meaningful when isUnique is * set to true. * @param sortBufferSize The size(MB) of sort buffer used when creating index, zero means don't use sort * buffer. * @throws BaseException If error happens. */ public void createIndex(String indexName, String indexKeys, boolean isUnique, boolean enforced, int sortBufferSize) throws BaseException { BSONObject k = null; if (indexKeys != null) { k = (BSONObject) JSON.parse(indexKeys); } createIndex(indexName, k, isUnique, enforced, sortBufferSize); } /** * Create a index with indexName and indexKeys * * @param indexName The index indexName. * @param indexKeys The index keys in JSON format, like: { "a":1, "b":-1}. * @param isUnique Whether the index elements are unique or not. * @param enforced Whether the index is enforced unique, this element is meaningful when isUnique is * set to true. * @throws BaseException If error happens. */ public void createIndex(String indexName, BSONObject indexKeys, boolean isUnique, boolean enforced) throws BaseException { createIndex(indexName, indexKeys, isUnique, enforced, SdbConstants.IXM_SORT_BUFFER_DEFAULT_SIZE); } /** * Create a index with indexName and indexKeys. * * @param indexName The index indexName. * @param indexKeys The index keys in JSON format, like: "{\"a\":1, \"b\":-1}". * @param isUnique Whether the index elements are unique or not. * @param enforced Whether the index is enforced unique, this element is meaningful when isUnique is * set to true. * @throws BaseException If error happens. */ public void createIndex(String indexName, String indexKeys, boolean isUnique, boolean enforced) throws BaseException { BSONObject k = null; if (indexKeys != null) { k = (BSONObject) JSON.parse(indexKeys); } createIndex(indexName, k, isUnique, enforced, SdbConstants.IXM_SORT_BUFFER_DEFAULT_SIZE); } /** * Remove the named index of current collection. * * @param indexName The index indexName. * @throws BaseException If error happens. */ public void dropIndex(String indexName) throws BaseException { BSONObject index = new BasicBSONObject(); index.put("", indexName); BSONObject dropObj = new BasicBSONObject(); dropObj.put(SdbConstants.FIELD_COLLECTION, collectionFullName); dropObj.put(SdbConstants.FIELD_INDEX, index); AdminRequest request = new AdminRequest(AdminCommand.DROP_INDEX, dropObj); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, indexName); sequoiadb.upsertCache(collectionFullName); } /** * Get the amount of documents in current collection. * * @return the amount of matching documents * @throws BaseException If error happens. */ public long getCount() throws BaseException { return getCount(""); } /** * Get the amount of matching documents in current collection. * * @param matcher the matching rule * @return the amount of matching documents * @throws BaseException If error happens. */ public long getCount(String matcher) throws BaseException { BSONObject con = null; if (matcher != null) { con = (BSONObject) JSON.parse(matcher); } return getCount(con); } /** * Get the amount of matching documents in current collection. * * @param matcher The matching rule, when condition is null, the return amount contains all the * records. * @return the amount of matching documents * @throws BaseException If error happens. */ public long getCount(BSONObject matcher) throws BaseException { return getCount(matcher, null); } /** * Get the count of matching BSONObject in current collection. * * @param matcher The matching rule, when condition is null, the return amount contains all the * records. * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @return The count of matching BSONObjects * @throws BaseException If error happens. */ public long getCount(BSONObject matcher, BSONObject hint) throws BaseException { BSONObject newHint = new BasicBSONObject(); newHint.put(SdbConstants.FIELD_COLLECTION, collectionFullName); if (null != hint) { newHint.put(SdbConstants.FIELD_NAME_HINT, hint); } AdminRequest request = new AdminRequest(AdminCommand.GET_COUNT, matcher, newHint); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "condition = " + matcher + ", hint = " + hint; sequoiadb.throwIfError(response, msg); } sequoiadb.upsertCache(collectionFullName); DBCursor cursor = new DBCursor(response, sequoiadb); BSONObject object; try { object = cursor.getNext(); } finally { cursor.close(); } return (Long) object.get(SdbConstants.FIELD_TOTAL); } /** * Split the specified collection from source group to target group by range. * * @param sourceGroupName the source group name * @param destGroupName the destination group name * @param splitCondition the split condition * @param splitEndCondition the split end condition or null, only usable when "ShardingType" is "range". eg:If * we create a collection with the option * {ShardingKey:{"age":1},ShardingType:"range"}, we can fill {age:30} as the * splitCondition, and fill {age:60} as the splitEndCondition. when split, the target * group will get the records whose age's hash value are in [30,60). If * splitEndCondition is null, they are in [30,max). * @throws BaseException If error happens. */ public void split(String sourceGroupName, String destGroupName, BSONObject splitCondition, BSONObject splitEndCondition) throws BaseException { if ((null == sourceGroupName || sourceGroupName.equals("")) || (null == destGroupName || destGroupName.equals("")) || null == splitCondition) { throw new BaseException(SDBError.SDB_INVALIDARG, "null parameter"); } BSONObject obj = new BasicBSONObject(); obj.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); obj.put(SdbConstants.FIELD_NAME_SOURCE, sourceGroupName); obj.put(SdbConstants.FIELD_NAME_TARGET, destGroupName); obj.put(SdbConstants.FIELD_NAME_SPLITQUERY, splitCondition); if (null != splitEndCondition) { obj.put(SdbConstants.FIELD_NAME_SPLITENDQUERY, splitEndCondition); } AdminRequest request = new AdminRequest(AdminCommand.SPLIT, obj); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "sourceGroupName = " + sourceGroupName + ", destGroupName = " + destGroupName + ", splitCondition = " + splitCondition + ", splitEndCondition = " + splitEndCondition; sequoiadb.throwIfError(response, msg); } sequoiadb.upsertCache(collectionFullName); } /** * Split the specified collection from source group to target group by percent. * * @param sourceGroupName the source group name * @param destGroupName the destination group name * @param percent the split percent, Range:(0,100] * @throws BaseException If error happens. */ public void split(String sourceGroupName, String destGroupName, double percent) throws BaseException { if ((null == sourceGroupName || sourceGroupName.equals("")) || (null == destGroupName || destGroupName.equals("")) || (percent <= 0.0 || percent > 100.0)) { throw new BaseException(SDBError.SDB_INVALIDARG); } BSONObject obj = new BasicBSONObject(); obj.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); obj.put(SdbConstants.FIELD_NAME_SOURCE, sourceGroupName); obj.put(SdbConstants.FIELD_NAME_TARGET, destGroupName); obj.put(SdbConstants.FIELD_NAME_SPLITPERCENT, percent); AdminRequest request = new AdminRequest(AdminCommand.SPLIT, obj); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "sourceGroupName = " + sourceGroupName + ", destGroupName = " + destGroupName + ", percent = " + percent; sequoiadb.throwIfError(response, msg); } sequoiadb.upsertCache(collectionFullName); } /** * Split the specified collection from source group to target group by range asynchronously. * * @param sourceGroupName the source group name * @param destGroupName the destination group name * @param splitCondition the split condition * @param splitEndCondition the split end condition or null, only usable when "ShardingType" is "range". eg:If * we create a collection with the option * {ShardingKey:{"age":1},ShardingType:"range"}, we can fill {age:30} as the * splitCondition, and fill {age:60} as the splitEndCondition. when split, the target * group will get the records whose age's hash values are in [30,60). If * splitEndCondition is null, they are in [30,max). * @return return the task id, we can use the return id to manage the sharding which is run * background. * @throws BaseException If error happens. * @see Sequoiadb#listTasks(BSONObject, BSONObject, BSONObject, BSONObject) * @see Sequoiadb#cancelTask(long, boolean) */ public long splitAsync(String sourceGroupName, String destGroupName, BSONObject splitCondition, BSONObject splitEndCondition) throws BaseException { if ((null == sourceGroupName || sourceGroupName.equals("")) || (null == destGroupName || destGroupName.equals("")) || null == splitCondition) { throw new BaseException(SDBError.SDB_INVALIDARG); } BSONObject obj = new BasicBSONObject(); obj.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); obj.put(SdbConstants.FIELD_NAME_ASYNC, true); obj.put(SdbConstants.FIELD_NAME_SOURCE, sourceGroupName); obj.put(SdbConstants.FIELD_NAME_TARGET, destGroupName); obj.put(SdbConstants.FIELD_NAME_SPLITQUERY, splitCondition); if (null != splitEndCondition) { obj.put(SdbConstants.FIELD_NAME_SPLITENDQUERY, splitEndCondition); } AdminRequest request = new AdminRequest(AdminCommand.SPLIT, obj); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "sourceGroupName = " + sourceGroupName + ", destGroupName = " + destGroupName + ", splitCondition = " + splitCondition + ", splitEndCondition = " + splitEndCondition; sequoiadb.throwIfError(response, msg); } BSONObject result; DBCursor cursor = new DBCursor(response, sequoiadb); try { if (!cursor.hasNext()) { throw new BaseException(SDBError.SDB_CAT_TASK_NOTFOUND); } result = cursor.getNext(); } finally { cursor.close(); } boolean flag = result.containsField(SdbConstants.FIELD_NAME_TASKID); if (!flag) { throw new BaseException(SDBError.SDB_CAT_TASK_NOTFOUND); } sequoiadb.upsertCache(collectionFullName); long taskid = (Long) result.get(SdbConstants.FIELD_NAME_TASKID); return taskid; } /** * Split the specified collection from source group to target group by percent asynchronously. * * @param sourceGroupName the source group name * @param destGroupName the destination group name * @param percent the split percent, Range:(0,100] * @return return the task id, we can use the return id to manage the sharding which is run * background. * @throws BaseException If error happens. */ public long splitAsync(String sourceGroupName, String destGroupName, double percent) throws BaseException { if ((null == sourceGroupName || sourceGroupName.equals("")) || (null == destGroupName || destGroupName.equals("")) || (percent <= 0.0 || percent > 100.0)) { throw new BaseException(SDBError.SDB_INVALIDARG); } BSONObject obj = new BasicBSONObject(); obj.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); obj.put(SdbConstants.FIELD_NAME_ASYNC, true); obj.put(SdbConstants.FIELD_NAME_SOURCE, sourceGroupName); obj.put(SdbConstants.FIELD_NAME_TARGET, destGroupName); obj.put(SdbConstants.FIELD_NAME_SPLITPERCENT, percent); AdminRequest request = new AdminRequest(AdminCommand.SPLIT, obj); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "sourceGroupName = " + sourceGroupName + ", destGroupName = " + destGroupName + ", percent = " + percent; sequoiadb.throwIfError(response, msg); } BSONObject result; DBCursor cursor = new DBCursor(response, sequoiadb); try { if (!cursor.hasNext()) { throw new BaseException(SDBError.SDB_CAT_TASK_NOTFOUND); } result = cursor.getNext(); } finally { cursor.close(); } boolean flag = result.containsField(SdbConstants.FIELD_NAME_TASKID); if (!flag) { throw new BaseException(SDBError.SDB_CAT_TASK_NOTFOUND); } sequoiadb.upsertCache(collectionFullName); long taskid = (Long) result.get(SdbConstants.FIELD_NAME_TASKID); return taskid; } /** * Execute aggregate operation in current collection. * * @param objs The Bson object of rule list, can't be null * @throws BaseException If error happens. */ public DBCursor aggregate(List objs) throws BaseException { if (objs == null || objs.size() == 0) { throw new BaseException(SDBError.SDB_INVALIDARG); } AggregateRequest request = new AggregateRequest(collectionFullName, objs); SdbReply response = sequoiadb.requestAndResponse(request); int flags = response.getFlag(); if (flags != 0) { if (flags == SDBError.SDB_DMS_EOC.getErrorCode()) { return null; } else { sequoiadb.throwIfError(response, objs); } } sequoiadb.upsertCache(collectionFullName); DBCursor cursor = new DBCursor(response, sequoiadb); return cursor; } /** * Get index blocks' or data blocks' information for concurrent query. * * @param matcher the matching rule, return all the meta information if null * @param orderBy the ordered rule, never sort if null * @param hint Specified the index used to scan data. e.g. {"":"ageIndex"} means using index * "ageIndex" to scan data(index scan); {"":null} means table scan. when hint is * null, database automatically match the optimal index to scan data. * @param skipRows The rows to be skipped * @param returnRows return the specified amount of documents, when returnRows is 0, return nothing, * when returnRows is -1, return all the documents * @param flag The flag to use which form for record data 0: bson stream 1: binary data stream, * form: col1|col2|col3 * @return DBCursor of data * @throws BaseException If error happens. */ public DBCursor getQueryMeta(BSONObject matcher, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows, int flag) throws BaseException { BSONObject newHint = new BasicBSONObject(); newHint.put("Collection", this.collectionFullName); if (null == hint || hint.isEmpty()) { BSONObject empty = new BasicBSONObject(); newHint.put("Hint", empty); } else { newHint.put("Hint", hint); } QueryRequest request = new QueryRequest(AdminCommand.GET_QUERYMETA, matcher, null, orderBy, newHint, skipRows, returnRows, flag); SdbReply response = sequoiadb.requestAndResponse(request); int flags = response.getFlag(); if (flags != 0) { if (flags == SDBError.SDB_DMS_EOC.getErrorCode()) { return null; } else { String msg = "query = " + matcher + ", hint = " + hint + ", orderBy = " + orderBy + ", skipRows = " + skipRows + ", returnRows = " + returnRows; sequoiadb.throwIfError(response, msg); } } sequoiadb.upsertCache(collectionFullName); DBCursor cursor = new DBCursor(response, sequoiadb); return cursor; } /** * Attach the specified collection. * * @param subClFullName The full name of the sub-collection * @param options The low boundary and up boundary eg: {"LowBound":{a:1},"UpBound":{a:100}} * @throws BaseException If error happens. */ public void attachCollection(String subClFullName, BSONObject options) throws BaseException { if (null == subClFullName || subClFullName.equals("") || null == options || null == collectionFullName || collectionFullName.equals("")) { throw new BaseException(SDBError.SDB_INVALIDARG, "sub collection name or options is empty or null"); } BSONObject newOptions = new BasicBSONObject(); newOptions.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); newOptions.put(SdbConstants.FIELD_NAME_SUBCLNAME, subClFullName); newOptions.putAll(options); AdminRequest request = new AdminRequest(AdminCommand.ATTACH_CL, newOptions); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "subCollectionName = " + subClFullName + ", options = " + options; sequoiadb.throwIfError(response, msg); } sequoiadb.upsertCache(collectionFullName); } /** * Detach the specified collection. * * @param subClFullName The full name of the sub-collection * @throws BaseException If error happens. */ public void detachCollection(String subClFullName) throws BaseException { if (null == subClFullName || subClFullName.equals("") || null == collectionFullName || collectionFullName.equals("")) { throw new BaseException(SDBError.SDB_INVALIDARG, subClFullName); } BSONObject options = new BasicBSONObject(); options.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); options.put(SdbConstants.FIELD_NAME_SUBCLNAME, subClFullName); AdminRequest request = new AdminRequest(AdminCommand.DETACH_CL, options); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, subClFullName); sequoiadb.upsertCache(collectionFullName); } private void alterInternal(String taskName, BSONObject options, boolean allowNullArgs) throws BaseException { if (null == options && !allowNullArgs) { throw new BaseException(SDBError.SDB_INVALIDARG, "options is null"); } BSONObject argumentObj = new BasicBSONObject(); argumentObj.put(SdbConstants.FIELD_NAME_NAME, taskName); argumentObj.put(SdbConstants.FIELD_NAME_ARGS, options); BSONObject alterObject = new BasicBSONObject(); alterObject.put(SdbConstants.FIELD_NAME_ALTER, argumentObj); alterCollection(alterObject); } /** * Alter the attributes of current collection. Can't alter attributes about split in partition * collection; After altering a collection to be a partition collection, need to split this * collection manually. * * @param options The options for altering current collection are as below: *
    *
  • ReplSize : Assign how many replica nodes need to be synchronized when a write * request(insert, update, etc) is executed *
  • ShardingKey : Assign the sharding key *
  • ShardingType : Assign the sharding type *
  • Partition : When the ShardingType is "hash", need to assign Partition, it's * the bucket number for hash, the range is [2^3,2^20]. *
  • CompressionType : The compression type of data, could be "snappy" or "lzw" *
  • EnsureShardingIndex : Assign to true to build sharding index *
  • StrictDataMode : Using strict date mode in numeric operations or not e.g. * {RepliSize:0, ShardingKey:{a:1}, ShardingType:"hash", Partition:1024} *
  • AutoIncrement : Assign attributes of an autoincrement field or batch * autoincrement fields. e.g. * {AutoIncrement:{Field:"a",MaxValue:2000}},{AutoIncrement:[{Field:"a",MaxValue:2000},{Field:"a",MaxValue:4000}]} *
* @throws BaseException If error happens. */ public void alterCollection(BSONObject options) throws BaseException { if (null == options) { throw new BaseException(SDBError.SDB_INVALIDARG, "options is null"); } BSONObject newObj = new BasicBSONObject(); if (!options.containsField(SdbConstants.FIELD_NAME_ALTER)) { newObj.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); newObj.put(SdbConstants.FIELD_NAME_OPTIONS, options); } else { Object tmpAlter = options.get(SdbConstants.FIELD_NAME_ALTER); if (tmpAlter instanceof BasicBSONObject || tmpAlter instanceof BasicBSONList) { newObj.put(SdbConstants.FIELD_NAME_ALTER, tmpAlter); } else { throw new BaseException(SDBError.SDB_INVALIDARG, options.toString()); } newObj.put(SdbConstants.FIELD_NAME_ALTER_TYPE, SdbConstants.SDB_ALTER_CL); newObj.put(SdbConstants.FIELD_NAME_VERSION, SdbConstants.SDB_ALTER_VERSION); newObj.put(SdbConstants.FIELD_NAME_NAME, collectionFullName); if (options.containsField(SdbConstants.FIELD_NAME_OPTIONS)) { Object tmpOptions = options.get(SdbConstants.FIELD_NAME_OPTIONS); if (tmpOptions instanceof BasicBSONObject) { newObj.put(SdbConstants.FIELD_NAME_OPTIONS, tmpOptions); } else { throw new BaseException(SDBError.SDB_INVALIDARG, options.toString()); } } } AdminRequest request = new AdminRequest(AdminCommand.ALTER_COLLECTION, newObj); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, options); sequoiadb.upsertCache(collectionFullName); } /** * Create auto-increment for current collection. * * @param options The options for creating auto-increment are as below: *
    *
  • Field : Auto-increment field name *
  • Increment : The interval between consecutive values *
  • StartValue : The first value for auto-increment *
  • MinValue : The minimum value *
  • MaxValue : The maximum value *
  • CacheSize : The number of values that are cached in catalog node *
  • AcquireSize : The number of values that are acquired by coord node *
  • Cycled : Whether generate the next value after reaching the maximum or minimum *
  • Generated : Whether generate value if the field has already exist. It can be * "default", "always" or "strict". *
  • default : Generate the value by default if field is not exist. It is default * value either. *
  • always : Always Generate the value, ignore the existent field. *
  • strict : Like 'default' behavior, but additionally check the type of field. If * not number, return error. e.g. {Field:"ID", StartValue:100, Generated:"always"} *
* @throws BaseException If error happens. */ public void createAutoIncrement(BSONObject options) { if (options == null || options.isEmpty()) { throw new BaseException(SDBError.SDB_INVALIDARG); } List optionsList = new ArrayList(); optionsList.add(options); createAutoIncrement(optionsList); } /** * Create one or more auto-increment for current collection. * * @param options The options of the auto-increment(s) * @throws BaseException If error happens. */ public void createAutoIncrement(List options) { if (options == null || options.size() == 0) { throw new BaseException(SDBError.SDB_INVALIDARG); } BSONObject obj = new BasicBSONObject(SdbConstants.FIELD_NAME_AUTOINCREMENT, options); alterInternal(SdbConstants.SDB_ALTER_CL_CRT_AUTOINC_FLD, obj, false); } /** * Drop auto-increment of current collection. * * @param fieldName The auto-increment field name * @throws BaseException If error happens. */ public void dropAutoIncrement(String fieldName) { if (fieldName == null || fieldName.length() == 0) { throw new BaseException(SDBError.SDB_INVALIDARG); } BSONObject obj = new BasicBSONObject(SdbConstants.FIELD_NAME_AUTOINC_FIELD, fieldName); alterInternal(SdbConstants.SDB_ALTER_CL_DROP_AUTOINC_FLD, obj, false); } /** * Drop one or more auto-increment of current collection. * * @param fieldNames The auto-increment field name(s) * @throws BaseException If error happens. */ public void dropAutoIncrement(List fieldNames) { if (fieldNames == null || fieldNames.size() == 0) { throw new BaseException(SDBError.SDB_INVALIDARG); } BSONObject obj = new BasicBSONObject(SdbConstants.FIELD_NAME_AUTOINC_FIELD, fieldNames); alterInternal(SdbConstants.SDB_ALTER_CL_DROP_AUTOINC_FLD, obj, false); } /** * Create the id index. * * @param options can be empty or specify option. e.g. {SortBufferSize:64} * @throws BaseException If error happens. */ public void createIdIndex(BSONObject options) throws BaseException { alterInternal(SdbConstants.SDB_ALTER_CRT_ID_INDEX, options, true); } /** * Drop the id index. * * @throws BaseException If error happens. */ public void dropIdIndex() throws BaseException { alterInternal(SdbConstants.SDB_ALTER_DROP_ID_INDEX, null, true); } /** * Alter the attributes of current collection to enable sharding * * @param options The options for altering current collection are as below: *
    *
  • ShardingKey : Assign the sharding key *
  • ShardingType : Assign the sharding type *
  • Partition : When the ShardingType is "hash", need to assign Partition, it's * the bucket number for hash, the range is [2^3,2^20]. *
  • EnsureShardingIndex : Assign to true to build sharding index *
* @throws BaseException If error happens. */ public void enableSharding(BSONObject options) throws BaseException { alterInternal(SdbConstants.SDB_ALTER_ENABLE_SHARDING, options, false); } /** * Alter the attributes of current collection to disable sharding * * @throws BaseException If error happens. */ public void disableSharding() throws BaseException { alterInternal(SdbConstants.SDB_ALTER_DISABLE_SHARDING, null, true); } /** * Alter the attributes of current collection to enable compression * * @param options The options for altering current collection are as below: *
    *
  • CompressionType : The compression type of data, could be "snappy" or "lzw" *
* @throws BaseException If error happens. */ public void enableCompression(BSONObject options) throws BaseException { alterInternal(SdbConstants.SDB_ALTER_ENABLE_COMPRESSION, options, true); } /** * Alter the attributes of current collection to disable compression * * @throws BaseException If error happens. */ public void disableCompression() throws BaseException { alterInternal(SdbConstants.SDB_ALTER_DISABLE_COMPRESSION, null, true); } /** * Alter the attributes of current collection Can't alter attributes about split in partition * collection; After altering a collection to be a partition collection, need to split this * collection manually. * * @param options The options for altering current collection are as below: *
    *
  • ReplSize : Assign how many replica nodes need to be synchronized when a write * request(insert, update, etc) is executed *
  • ShardingKey : Assign the sharding key *
  • ShardingType : Assign the sharding type *
  • Partition : When the ShardingType is "hash", need to assign Partition, it's * the bucket number for hash, the range is [2^3,2^20]. *
  • CompressionType : The compression type of data, could be "snappy" or "lzw" *
  • EnsureShardingIndex : Assign to true to build sharding index *
  • StrictDataMode : Using strict date mode in numeric operations or not e.g. * {RepliSize:0, ShardingKey:{a:1}, ShardingType:"hash", Partition:1024} *
  • AutoIncrement : Assign attributes of an autoincrement field or batch * autoincrement fields. e.g. {AutoIncrement:{Field:"a",MaxValue:2000}}, * {AutoIncrement:[{Field:"a",MaxValue:2000},{Field:"a",MaxValue:4000}]} *
* @throws BaseException If error happens. */ public void setAttributes(BSONObject options) throws BaseException { alterInternal(SdbConstants.SDB_ALTER_SET_ATTRIBUTES, options, false); } private void _update(int flag, BSONObject matcher, BSONObject modifier, BSONObject hint) throws BaseException { UpdateRequest request = new UpdateRequest(collectionFullName, matcher, modifier, hint, flag); SdbReply response = sequoiadb.requestAndResponse(request); if (response.getFlag() != 0) { String msg = "matcher = " + matcher + ", modifier = " + modifier + ", hint = " + hint; sequoiadb.throwIfError(response, msg); } sequoiadb.upsertCache(collectionFullName); } /** * Get all of the lobs in current collection. * * @return DBCursor of lobs * @throws BaseException If error happens. */ public DBCursor listLobs() throws BaseException { return listLobs(null, null, null, null, 0, -1); } private boolean isEmptyObj(BSONObject o) { if (null == o) { return true; } return o.isEmpty(); } /** * Get the lobs in current collection. * * @param matcher the matching rule, return all the lobs if null * @param selector the selective rule, return the whole lobs if null * @param orderBy the ordered rule, never sort if null * @param hint Specified options. e.g. {"ListPieces": 1} means get the detail piece info of lobs; * @param skipRows skip the first numToSkip lobs, never skip if this parameter is 0 * @param returnRows return the specified amount of lobs, when returnRows is 0, return nothing, when * returnRows is -1, return all the lobs * @return DBCursor of lobs * @throws BaseException If error happens. */ public DBCursor listLobs(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows) throws BaseException { BSONObject newHint = new BasicBSONObject(); if (null != hint) { newHint.putAll(hint); } newHint.put(SdbConstants.FIELD_COLLECTION, collectionFullName); if (!sequoiadb.getIsOldVersionLobServer()) { BaseException savedError = null; try { isOldLobServer = false; DBCursor cursor = _listLobs(matcher, selector, orderBy, newHint, skipRows, returnRows); return cursor; } catch (BaseException e) { if (!isOldLobServer) { throw e; } savedError = e; } // when we come here, we got rc == -6. there are two cases: // case 1: having invalid paraments. // case 2: the remote engine is older than v3.2.4. // case 1: test having invalid paraments or not // only when we have input paraments, we need to do this test. if (!isEmptyObj(matcher) || !isEmptyObj(selector) || !isEmptyObj(orderBy) || !isEmptyObj(hint) || skipRows != 0 || returnRows != -1) { try { isOldLobServer = false; BSONObject tmpHint = new BasicBSONObject(); tmpHint.put(SdbConstants.FIELD_COLLECTION, collectionFullName); // make sure no input paraments can affect this test DBCursor tmpCursor = _listLobs(null, null, null, tmpHint, 0, -1); tmpCursor.close(); throw savedError; } catch (BaseException e) { if (!isOldLobServer) { throw e; } } } // case 2: // when we come here, the remote engine must be an old engine. DBCursor cursor = _listLobs(newHint, null, null, null, 0, -1); sequoiadb.setIsOldVersionLobServer(true); return cursor; } else { // deal with old version engine. clName is in the query field return _listLobs(newHint, null, null, null, 0, -1); } } private DBCursor _listLobs(BSONObject matcher, BSONObject selector, BSONObject orderBy, BSONObject hint, long skipRows, long returnRows) throws BaseException { AdminRequest request = new AdminRequest(AdminCommand.LIST_LOBS, matcher, selector, orderBy, hint, skipRows, returnRows); SdbReply response = sequoiadb.requestAndResponse(request); int flag = response.getFlag(); if (flag == SDBError.SDB_INVALIDARG.getErrorCode()) { isOldLobServer = true; } sequoiadb.throwIfError(response); sequoiadb.upsertCache(collectionFullName); DBCursor cursor = new DBCursor(response, sequoiadb); return cursor; } /** * Create a lob. * * @return DBLob object * @throws BaseException If error happens.. */ public DBLob createLob() throws BaseException { return createLob(null); } /** * Just create a lobID from server. * * @param d LobID's relative time. if d is NULL the relative time will be server's system time * @return ObjectId object * @throws BaseException If error happens.. */ public ObjectId createLobID(Date d) throws BaseException { BSONObject createLobID = null; if (null != d) { SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd-HH.mm.ss"); createLobID = new BasicBSONObject(DBLobImpl.FIELD_NAME_LOB_CREATE_TIME, sdf.format(d)); } LobCreateIDRequest request = new LobCreateIDRequest(createLobID); SdbReply response = sequoiadb.requestAndResponse(request, SdbReply.class); sequoiadb.throwIfError(response, createLobID); ResultSet r = response.getResultSet(); if (!r.hasNext()) { throw new BaseException(SDBError.SDB_INVALIDARG, "Response must have obj"); } BSONObject o = r.getNext(); if (o == null) { throw new BaseException(SDBError.SDB_SYS, "expect a return obj to get oid, but got null"); } return (ObjectId) o.get(DBLobImpl.FIELD_NAME_LOB_OID); } /** * Just create a lobID from server. * * @return ObjectId object * @throws BaseException If error happens.. */ public ObjectId createLobID() throws BaseException { return createLobID(null); } /** * Create a lob with a given id. * * @param id the lob's id. if id is null, it will be generated in this function * @return DBLob object * @throws BaseException If error happens.. */ public DBLob createLob(ObjectId id) throws BaseException { DBLobImpl lob = new DBLobImpl(this); lob.open(id, DBLobImpl.SDB_LOB_CREATEONLY); // upsert cache sequoiadb.upsertCache(collectionFullName); return lob; } /** * Open an existing lob with id. * * @param id the lob's id. * @param mode open mode: DBLob.SDB_LOB_READ for reading, DBLob.SDB_LOB_SHAREREAD for share reading, * DBLob.SDB_LOB_WRITE for writing, DBLob.SDB_LOB_SHAREREAD|DBLob.SDB_LOB_WRITE for both * reading and writing. if one lob has been opened by DBLob.SDB_LOB_READ mode, it can't * be opened by DBLob.SDB_LOB_WRITE mode; However, if one lob has been opened by * DBLob.SDB_LOB_SHAREREAD mode, it can be opened by DBLob.SDB_LOB_WRITE mode * @return DBLob object * @throws BaseException If error happens.. */ public DBLob openLob(ObjectId id, int mode) throws BaseException { if (!DBLobImpl.hasWriteMode(mode) && !DBLobImpl.isReadOnlyMode(mode)) { throw new BaseException(SDBError.SDB_INVALIDARG, "mode is unsupported: " + mode); } DBLobImpl lob = new DBLobImpl(this); lob.open(id, mode); // upsert cache sequoiadb.upsertCache(collectionFullName); return lob; } /** * Open an existing lob with id. * * @param id the lob's id. * @return DBLob object * @throws BaseException If error happens. */ public DBLob openLob(ObjectId id) throws BaseException { return openLob(id, DBLob.SDB_LOB_READ); } /** * Remove an existing lob. * * @param lobId the lob's id. * @throws BaseException If error happens.. */ public void removeLob(ObjectId lobId) throws BaseException { BSONObject removeObj = new BasicBSONObject(); removeObj.put(SdbConstants.FIELD_COLLECTION, collectionFullName); removeObj.put(DBLobImpl.FIELD_NAME_LOB_OID, lobId); LobRemoveRequest request = new LobRemoveRequest(removeObj); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, removeObj); sequoiadb.upsertCache(collectionFullName); } /** * Truncate an existing lob. * * @param lobId the lob's id. * @param length the truncate length * @throws BaseException If error happens. */ public void truncateLob(ObjectId lobId, long length) throws BaseException { if (length < 0) { throw new BaseException(SDBError.SDB_INVALIDARG, "Invalid length"); } BSONObject truncateObj = new BasicBSONObject(); truncateObj.put(SdbConstants.FIELD_COLLECTION, collectionFullName); truncateObj.put(DBLobImpl.FIELD_NAME_LOB_OID, lobId); truncateObj.put(DBLobImpl.FIELD_NAME_LOB_LENGTH, length); LobTruncateRequest request = new LobTruncateRequest(truncateObj); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, truncateObj); sequoiadb.upsertCache(collectionFullName); } /** * Truncate the collection. * * @throws BaseException If error happens. */ public void truncate() throws BaseException { BSONObject options = new BasicBSONObject(); options.put(SdbConstants.FIELD_COLLECTION, collectionFullName); AdminRequest request = new AdminRequest(AdminCommand.TRUNCATE, options); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, options); sequoiadb.upsertCache(collectionFullName); } /** * Pop records from the collection. * * @param options the pop option for the operation, including a record LogicalID, and an optional * Direction: 1 for forward pop and -1 for backward pop * @throws BaseException If error happens. */ public void pop(BSONObject options) throws BaseException { if (options == null) { throw new BaseException(SDBError.SDB_INVALIDARG, "options is null"); } BSONObject newObj = new BasicBSONObject(); newObj.put(SdbConstants.FIELD_COLLECTION, collectionFullName); Object lidObj = options.get(SdbConstants.FIELD_NAME_LOGICALID); if (lidObj instanceof Integer || lidObj instanceof Long) { newObj.put(SdbConstants.FIELD_NAME_LOGICALID, lidObj); } else { throw new BaseException(SDBError.SDB_INVALIDARG, options.toString()); } Object directObj = options.get(SdbConstants.FIELD_NAME_DIRECTION); if (directObj == null) { newObj.put(SdbConstants.FIELD_NAME_DIRECTION, 1); } else if (directObj instanceof Integer) { newObj.put(SdbConstants.FIELD_NAME_DIRECTION, directObj); } else { throw new BaseException(SDBError.SDB_INVALIDARG, options.toString()); } AdminRequest request = new AdminRequest(AdminCommand.POP, newObj); SdbReply response = sequoiadb.requestAndResponse(request); sequoiadb.throwIfError(response, newObj); sequoiadb.upsertCache(collectionFullName); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy