protected void parseLet() {
    let = new LinkedHashMap<String, Object>();

    boolean stop = false;
    while (!stop) {
      // PARSE THE KEY
      final String letName = parserNextWord(false);

      parserOptionalKeyword("=");

      parserNextWord(false, " =><,\r\n", true);

      // PARSE THE VALUE
      String letValueAsString = parserGetLastWord();
      final Object letValue;

      // TRY TO PARSE AS FUNCTION
      final Object func = OSQLHelper.getFunction(parsedTarget, letValueAsString);
      if (func != null) letValue = func;
      else if (letValueAsString.startsWith("(")) {
        letValue =
            new OSQLSynchQuery<Object>(
                letValueAsString.substring(1, letValueAsString.length() - 1));
      } else letValue = letValueAsString;

      let.put(letName, letValue);
      stop = parserGetLastSeparator() == ' ';
    }
  }
  protected void parseValues() {
    final int beginFields = parserGetCurrentPosition();

    final int endFields = parserText.indexOf(')', beginFields + 1);
    if (endFields == -1) throwSyntaxErrorException("Missed closed brace");

    final ArrayList<String> fieldNames = new ArrayList<String>();
    parserSetCurrentPosition(
        OStringSerializerHelper.getParameters(parserText, beginFields, endFields, fieldNames));
    if (fieldNames.size() == 0)
      throwSyntaxErrorException("Set of fields is empty. Example: (name, surname)");

    // REMOVE QUOTATION MARKS IF ANY
    for (int i = 0; i < fieldNames.size(); ++i)
      fieldNames.set(i, OStringSerializerHelper.removeQuotationMarks(fieldNames.get(i)));

    parserRequiredKeyword(KEYWORD_VALUES);
    parserSkipWhiteSpaces();
    if (parserIsEnded() || parserText.charAt(parserGetCurrentPosition()) != '(') {
      throwParsingException("Set of values is missed. Example: ('Bill', 'Stuart', 300)");
    }

    int blockStart = parserGetCurrentPosition();
    int blockEnd = parserGetCurrentPosition();

    final List<String> records =
        OStringSerializerHelper.smartSplit(
            parserText, new char[] {','}, blockStart, -1, true, true, false);
    for (String record : records) {

      final List<String> values = new ArrayList<String>();
      blockEnd += OStringSerializerHelper.getParameters(record, 0, -1, values);

      if (blockEnd == -1)
        throw new OCommandSQLParsingException(
            "Missed closed brace. Use " + getSyntax(), parserText, blockStart);

      if (values.isEmpty())
        throw new OCommandSQLParsingException(
            "Set of values is empty. Example: ('Bill', 'Stuart', 300). Use " + getSyntax(),
            parserText,
            blockStart);

      if (values.size() != fieldNames.size())
        throw new OCommandSQLParsingException(
            "Fields not match with values", parserText, blockStart);

      // TRANSFORM FIELD VALUES
      final Map<String, Object> fields = new LinkedHashMap<String, Object>();
      for (int i = 0; i < values.size(); ++i)
        fields.put(
            fieldNames.get(i),
            OSQLHelper.parseValue(
                this, OStringSerializerHelper.decode(values.get(i).trim()), context));

      newRecords.add(fields);
      blockStart = blockEnd;
    }
  }
  /** Execute the INSERT and return the ODocument object created. */
  public Object execute(final Map<Object, Object> iArgs) {
    if (newRecords == null && content == null)
      throw new OCommandExecutionException(
          "Cannot execute the command because it has not been parsed yet");

    final OCommandParameters commandParameters = new OCommandParameters(iArgs);
    if (indexName != null) {
      if (newRecords == null) throw new OCommandExecutionException("No key/value found");

      final OIndex<?> index = getDatabase().getMetadata().getIndexManager().getIndex(indexName);
      if (index == null)
        throw new OCommandExecutionException("Target index '" + indexName + "' not found");

      // BIND VALUES
      Map<String, Object> result = null;

      for (Map<String, Object> candidate : newRecords) {
        index.put(
            getIndexKeyValue(commandParameters, candidate),
            getIndexValue(commandParameters, candidate));
        result = candidate;
      }

      // RETURN LAST ENTRY
      return new ODocument(result);
    } else {

      // CREATE NEW DOCUMENTS
      final List<ODocument> docs = new ArrayList<ODocument>();
      if (newRecords != null) {
        for (Map<String, Object> candidate : newRecords) {
          final ODocument doc = className != null ? new ODocument(className) : new ODocument();
          OSQLHelper.bindParameters(doc, candidate, commandParameters, context);

          if (clusterName != null) {
            doc.save(clusterName);
          } else {
            doc.save();
          }
          docs.add(doc);
        }

        if (docs.size() == 1) return docs.get(0);
        else return docs;
      } else if (content != null) {
        final ODocument doc = className != null ? new ODocument(className) : new ODocument();
        doc.merge(content, true, false);
        doc.save();
        return doc;
      }
    }
    return null;
  }