text:
const MrrStatsService = require('../../lib/mrr');
const moment = require('moment');
const sinon = require('sinon');
const knex = require('knex').default;
require('should');

describe('MrrStatsService', function () {
    describe('getHistory', function () {
        /** @type {MrrStatsService} */
        let mrrStatsService;

        const today = '2000-01-10';
        const tomorrow = '2000-01-11';
        const yesterday = '2000-01-09';
        const dayBeforeYesterday = '2000-01-08';
        const twoDaysBeforeYesterday = '2000-01-07';

        after(function () {
            sinon.restore();
        });

        /** @type {import('knex').Knex} */
        let db;

        before(function () {
            const todayDate = moment(today).toDate();
            sinon.useFakeTimers(todayDate.getTime());
        });

        beforeEach(async function () {
            db = knex({client: 'sqlite3', connection: {filename: ':memory:'}, useNullAsDefault: true});
            mrrStatsService = new MrrStatsService({knex: db});

            await db.schema.createTable('members_paid_subscription_events', function (table) {
                table.string('currency');
                table.string('mrr_delta');
                table.date('created_at');
            });

            await db.schema.createTable('members_stripe_customers_subscriptions', function (table) {
                table.string('plan_currency');
                table.string('mrr');
            });
        });

        afterEach(async function () {
            await db.destroy();
        });

        it('Handles no data', async function () {
            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(1);

            // Note that currencies should always be sorted ascending, so EUR should be first.
            results[0].should.eql({
                date: today,
                mrr: 0,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 0,
                    currency: 'usd'
                }
            ]);
        });

        it('Always returns at least one value', async function () {
            await db('members_stripe_customers_subscriptions').insert([{
                plan_currency: 'usd',
                mrr: 1
            }, {
                plan_currency: 'eur',
                mrr: 2
            }]);

            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(2);

            // Note that currencies should always be sorted ascending, so EUR should be first.
            results[0].should.eql({
                date: today,
                mrr: 2,
                currency: 'eur'
            });
            results[1].should.eql({
                date: today,
                mrr: 1,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 2,
                    currency: 'eur'
                },
                {
                    mrr: 1,
                    currency: 'usd'
                }
            ]);
        });

        it('Does not substract delta of first event', async function () {
            await db('members_stripe_customers_subscriptions').insert([{
                plan_currency: 'usd',
                mrr: 5
            }]);
            await db('members_paid_subscription_events').insert([{
                created_at: today,
                mrr_delta: 5,
                currency: 'usd'
            }]);

            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(2);
            results[0].should.eql({
                date: yesterday,
                mrr: 0,
                currency: 'usd'
            });
            results[1].should.eql({
                date: today,
                mrr: 5,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 5,
                    currency: 'usd'
                }
            ]);
        });

        it('Correctly calculates deltas', async function () {
            await db('members_paid_subscription_events').insert([{
                created_at: yesterday,
                mrr_delta: 2,
                currency: 'usd'
            },
            {
                created_at: today,
                mrr_delta: 5,
                currency: 'usd'
            }]);

            await db('members_stripe_customers_subscriptions').insert([{
                plan_currency: 'usd',
                mrr: 2
            }, {
                plan_currency: 'usd',
                mrr: 5
            }]);

            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(3);
            results[0].should.eql({
                date: dayBeforeYesterday,
                mrr: 0,
                currency: 'usd'
            });
            results[1].should.eql({
                date: yesterday,
                mrr: 2,
                currency: 'usd'
            });
            results[2].should.eql({
                date: today,
                mrr: 7,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 7,
                    currency: 'usd'
                }
            ]);
        });

        it('Correctly calculates deltas for multiple currencies', async function () {
            await db('members_paid_subscription_events').insert([
                {
                    created_at: yesterday,
                    mrr_delta: 200,
                    currency: 'eur'
                },
                {
                    created_at: yesterday,
                    mrr_delta: 2,
                    currency: 'usd'
                },
                {
                    created_at: today,
                    mrr_delta: 800,
                    currency: 'eur'
                },
                {
                    created_at: today,
                    mrr_delta: 5,
                    currency: 'usd'
                }
            ]);

            await db('members_stripe_customers_subscriptions').insert([{
                plan_currency: 'eur',
                mrr: 200
            }, {
                plan_currency: 'usd',
                mrr: 2
            }, {
                plan_currency: 'eur',
                mrr: 800
            }, {
                plan_currency: 'usd',
                mrr: 5
            }, {
                plan_currency: 'eur',
                mrr: 200
            }]);

            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(6);
            results[0].should.eql({
                date: dayBeforeYesterday,
                mrr: 200,
                currency: 'eur'
            });
            results[1].should.eql({
                date: dayBeforeYesterday,
                mrr: 0,
                currency: 'usd'
            });
            results[2].should.eql({
                date: yesterday,
                mrr: 400,
                currency: 'eur'
            });
            results[3].should.eql({
                date: yesterday,
                mrr: 2,
                currency: 'usd'
            });
            results[4].should.eql({
                date: today,
                mrr: 1200,
                currency: 'eur'
            });
            results[5].should.eql({
                date: today,
                mrr: 7,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 1200,
                    currency: 'eur'
                },
                {
                    mrr: 7,
                    currency: 'usd'
                }
            ]);
        });

        it('Ignores invalid currencies in deltas', async function () {
            await db('members_paid_subscription_events').insert({
                created_at: today,
                mrr_delta: 200,
                currency: 'abc'
            });

            await db('members_stripe_customers_subscriptions').insert({
                plan_currency: 'usd',
                mrr: 7
            });

            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(1);
            results[0].should.eql({
                date: yesterday,
                mrr: 7,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 7,
                    currency: 'usd'
                }
            ]);
        });

        it('Ignores events in the future', async function () {
            await db('members_paid_subscription_events').insert([
                {
                    created_at: yesterday,
                    mrr_delta: 2,
                    currency: 'usd'
                },
                {
                    created_at: today,
                    mrr_delta: 5,
                    currency: 'usd'
                },
                {
                    created_at: tomorrow,
                    mrr_delta: 10,
                    currency: 'usd'
                }
            ]);

            await db('members_stripe_customers_subscriptions').insert({plan_currency: 'usd', mrr: 7});

            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(3);
            results[0].should.eql({
                date: dayBeforeYesterday,
                mrr: 0,
                currency: 'usd'
            });
            results[1].should.eql({
                date: yesterday,
                mrr: 2,
                currency: 'usd'
            });
            results[2].should.eql({
                date: today,
                mrr: 7,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 7,
                    currency: 'usd'
                }
            ]);
        });

        it('Correctly handles negative total MRR', async function () {
            await db('members_paid_subscription_events').insert([
                {
                    created_at: dayBeforeYesterday,
                    mrr_delta: 2,
                    currency: 'usd'
                },
                {
                    created_at: yesterday,
                    mrr_delta: -1000,
                    currency: 'usd'
                },
                {
                    created_at: today,
                    mrr_delta: 1000,
                    currency: 'usd'
                }
            ]);

            await db('members_stripe_customers_subscriptions').insert({plan_currency: 'usd', mrr: 7});

            const {data: results, meta} = await mrrStatsService.getHistory();
            results.length.should.eql(4);
            results[0].should.eql({
                date: twoDaysBeforeYesterday,
                mrr: 5,
                currency: 'usd'
            });
            results[1].should.eql({
                date: dayBeforeYesterday,
                // We are mainly testing that this should not be 1000!
                mrr: 7,
                currency: 'usd'
            });
            results[2].should.eql({
                date: yesterday,
                // Should never be shown negative (in fact it is -993 here)
                mrr: 0,
                currency: 'usd'
            });
            results[3].should.eql({
                date: today,
                mrr: 7,
                currency: 'usd'
            });
            meta.totals.should.eql([
                {
                    mrr: 7,
                    currency: 'usd'
                }
            ]);
        });
    });
});


text:
import escapeRegExp from 'utils/escapeRegExp';

const regExpCache = {};

export default function(haystack, needles) {
  return haystack.search(
    regExpCache[needles.join()] ||
      (regExpCache[needles.join()] = new RegExp(needles.map(escapeRegExp).join('|')))
  );
}

redpajama_set_name: RedPajamaGithub


text:
require 'rails_helper'

RSpec.describe 'Groups API' do
  describe 'GET show' do
    it 'returns a group', :show_in_doc do
      sign_in_as create :staff, :admin
      group = create(:group)

      get group_path(group, format: :json)

      expect(response.body).to match_serialized_json(group)
    end
  end

  describe 'GET index' do
    it 'returns a list of groups' do
      sign_in_as create :staff, :admin
      groups = create_list(:group, 2)

      get groups_path(format: :json)

      expect(response.body).to match_serialized_json(groups)
    end
  end

  describe 'POST create' do
    it 'creates a group' do
      sign_in_as create :staff, :admin
      group_attributes = attributes_for(:group)

      post groups_path(format: :json), group_attributes

      group = Group.last
      expect(response.body).to match_serialized_json(group)
    end
  end

  describe 'DELETE destroy' do
    it 'deletes a group' do
      sign_in_as create :staff, :admin
      group = create(:group)

      delete group_path(group, format: :json)

      expect(response).to be_successful
      expect(Group.find_by_id(group.id)).to be_nil
    end
  end
end


text:
package com.simon.arpe.ezyweather.net;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import com.squareup.okhttp.OkHttpClient;

public class ConnectionHelper {

public static String conntect(URL url){

		OkHttpClient client = new OkHttpClient();

	      HttpURLConnection connection = client.open(url);
	      InputStream in = null;
	      try {
	        // Read the response.
	        in = connection.getInputStream();
	        byte[] response = readFully(in);
	        return new String(response, "UTF-8");
	      }
	      catch(UnsupportedEncodingException uee){
	    	  uee.printStackTrace();
	      }

	      catch(IOException ioe){
	    	  ioe.printStackTrace();
	      }

	      finally {
	        if (in != null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
	      }
		return null;

	}

	private static byte[] readFully(InputStream in) throws IOException
	{
	    byte[] buffer = new byte[8192];
	    int bytesRead;
	    ByteArrayOutputStream output = new ByteArrayOutputStream();
	    while ((bytesRead = in.read(buffer)) != -1)
	    {
	        output.write(buffer, 0, bytesRead);
	    }
	    return output.toByteArray();
	}

}


text:
/*
	This file is part of the implementation for the technical paper

		Field-Aligned Online Surface Reconstruction
		Nico Schertler, Marco Tarini, Wenzel Jakob, Misha Kazhdan, Stefan Gumhold, Daniele Panozzo
		ACM TOG 36, 4, July 2017 (Proceedings of SIGGRAPH 2017)

	Use of this source code is granted via a BSD-style license, which can be found
	in License.txt in the repository root.

	@author Nico Schertler
*/

#pragma once

#include "osr/gui/DataGL.h"
#include "osr/gui/tools/Tool.h"
#include "osr/gui/tools/Selection.h"

#include <nsessentials/gui/AbstractViewer.h>

namespace osr {
	namespace gui {
		namespace tools
		{

			//Represents a modification tool that removes points within a user-defined region.
			class RemoveTool : public Tool
			{
			public:
				RemoveTool(nse::gui::AbstractViewer* viewer, DataGL& data, float& selectionRadius);

				void enterTool();
				void exitTool();

				void draw(const Matrix4f& mv, const Matrix4f& proj);

				bool mouseButtonEvent(const Eigen::Vector2i & p, int button, bool down, int modifiers);
				bool mouseMotionEvent(const Eigen::Vector2i & p, const Eigen::Vector2i & rel, int button, int modifiers);
				bool scrollEvent(const Eigen::Vector2i & p, const Eigen::Vector2f & rel);

			private:
				float& selectionRadius;

				DataGL& data;

				Selection selection;

				int pixelsMoved;

				nse::gui::AbstractViewer* viewer;
			};
		}
	}
}


text:
'use strict';

const common = require('x2node-common');
const rsparser = require('x2node-rsparser');

const selectQueryBuilder = require('./select-query-builder.js');

/////////////////////////////////////////////////////////////////////////////////
// FILTER PARAMETERS HANDLER
/////////////////////////////////////////////////////////////////////////////////

/**
 * Filter parameters handler used by a DBO. Any DBO that acts on a filtered set
 * of records (all except the insert) use a filter parameters handler to replace
 * parameter references in the SQL statements with the values provided to the DBO
 * execution method.
 *
 * @protected
 * @memberof module:x2node-dbos
 * @inner
 */
class FilterParamsHandler {

	/**
	 * Create new parameters handler for a DBO.
	 */
	constructor() {

		this._nextParamRef = 0;

		this._params = new Map();
	}

	/**
	 * Add parameter mapping.
	 *
	 * @param {string} paramName Parameter name.
	 * @param {function} valueFunc Function that given the parameter value
	 * provided with DBO call returns the ES literal for the value to include
	 * in the database statement.
	 * @returns {string} Parameter placeholder to include in the SQL in the
	 * form of "?{ref}", where "ref" is the parameter reference assigned by the
	 * handler.
	 */
	addParam(paramName, valueFunc) {

		const paramRef = String(this._nextParamRef++);

		this._params.set(paramRef, {
			name: paramName,
			valueFunc: valueFunc
		});

		return '?{' + paramRef + '}';
	}

	/**
	 * Get parameter value SQL expression.
	 *
	 * @param {module:x2node-dbos.DBDriver} dbDriver DB driver.
	 * @param {*} paramValue Parameter value from the DBO specification.
	 * @param {function} valueFunc Parameter value function (see
	 * addParam method).
	 * @param {string} paramName Parameter name (for error reporting only).
	 * @returns {string} Parameter value SQL expression to include in the
	 * database statement.
	 */
	paramValueToSql(dbDriver, paramValue, valueFunc, paramName) {

		const invalid = () => new common.X2UsageError(
			'Invalid ' + (paramName ? '"' + paramName + '"' : '') +
				' filter test parameter value: ' + String(paramValue) + '.');

		let preSql;
		if (valueFunc) {
			if ((paramValue === undefined) || (paramValue === null) || (
				((typeof paramValue) === 'number') &&
					!Number.isFinite(paramValue)) ||
				Array.isArray(paramValue))
				throw invalid();
			preSql = valueFunc(paramValue);
		} else {
			preSql = paramValue;
		}

		const sql = dbDriver.sql(preSql);
		if ((sql === null) || (sql === 'NULL'))
			throw invalid();

		return sql;
	}

	/**
	 * Get parameter value SQL expression given the parameter reference.
	 *
	 * @param {module:x2node-dbos.DBDriver} dbDriver DB driver.
	 * @param {Object.<string,*>} filterParams Parameters provided with the DBO
	 * execution call. Will throw error if not provided.
	 * @param {string} paramRef Parameter reference from the SQL.
	 * @returns {string} Parameter value SQL expression to include in the
	 * database statement.
	 * @throws {module:x2node-common.X2UsageError} If no value for the specified
	 * parameter reference.
	 */
	paramSql(dbDriver, filterParams, paramRef) {

		const ref = this._params.get(paramRef);
		const filterParam = (ref && filterParams && filterParams[ref.name]);
		if (filterParam === undefined)
			throw new common.X2UsageError(
				`Missing filter parameter "${ref.name}".`);

		const process = v => this.paramValueToSql(
			dbDriver, v, ref.valueFunc, ref.name);
		return (
			Array.isArray(filterParam) ?
				filterParam.map(v => process(v)).join(', ') :
				process(filterParam)
		);
	}
}

/////////////////////////////////////////////////////////////////////////////////
// COMMON COMMANDS
/////////////////////////////////////////////////////////////////////////////////

/**
 * Interface for DBO commands.
 *
 * @protected
 * @interface DBOCommand
 * @memberof module:x2node-dbos
 */
/**
 * Queue up the command execution.
 *
 * @function module:x2node-dbos.DBOCommand#queueUp
 * @param {Promise} promiseChain DBO execution result promise chain.
 * @param {module:x2node-dbos~DBOExecutionContext ctx DBO execution context.
 * @returns {Promise} New result promise chain with the command queued up.
 */

/**
 * Command that simply executes the configured SQL statement.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @implements module:x2node-dbos.DBOCommand
 */
class ExecuteStatementCommand {

	constructor(stmt, stmtId) {

		this._stmt = stmt;
		this._stmtId = stmtId;
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		const stmt = this._stmt;
		const stmtId = this._stmtId;
		return promiseChain.then(
			() => new Promise((resolve, reject) => {
				let sql;
				try {
					sql = ctx.replaceParams(stmt);
					ctx.log(`executing SQL: ${sql}`);
					ctx.dbDriver.executeUpdate(
						ctx.connection, sql, {
							onSuccess(affectedRows) {
								ctx.affectedRows(affectedRows, stmtId);
								resolve();
							},
							onError(err) {
								common.error(
									`error executing SQL [${sql}]`, err);
								reject(err);
							}
						}
					);
				} catch (err) {
					common.error(`error executing SQL [${sql || stmt}]`, err);
					reject(err);
				}
			}),
			err => Promise.reject(err)
		);
	}
}

/**
 * Index for the next anchor table name.
 *
 * @private
 * @type {number}
 */
let g_nextAnchorTableInd = 0;

/**
 * Command used to load matching record ids into a temporary table for a
 * multi-branch fetch operation.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @implements module:x2node-dbos.DBOCommand
 */
class LoadAnchorTableCommand {

	constructor(topTableName, idColumnName, idExpr, statementStump) {

		this._topTableName = topTableName;
		this._anchorTableName = `q_${topTableName}_${g_nextAnchorTableInd++}`;
		this._idColumnName = idColumnName;
		this._idExpr = idExpr;
		this._statementStump = statementStump;
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		const cmd = this;
		return promiseChain.then(
			() => new Promise((resolve, reject) => {
				try {
					let lastSql;
					ctx.dbDriver.selectIntoAnchorTable(
						ctx.connection, cmd._anchorTableName,
						cmd._topTableName, cmd._idColumnName, cmd._idExpr,
						ctx.replaceParams(cmd._statementStump), {
							trace(sql) {
								lastSql = sql;
								ctx.log(`executing SQL: ${sql}`);
							},
							onSuccess(numRows) {
								ctx.log(
									`anchor table ${this._anchorTableName} has` +
										` ${numRows} rows`);
								resolve();
							},
							onError(err) {
								common.error(
									`error executing SQL [${lastSql}]`, err);
								reject(err);
							}
						}
					);
				} catch (err) {
					common.error('error loading anchor table', err);
					reject(err);
				}
			}),
			err => Promise.reject(err)
		);
	}

	/**
	 * Anchor table name.
	 *
	 * @member {string}
	 * @readonly
	 */
	get anchorTableName() { return this._anchorTableName; }
}

/**
 * Property value generator command. When executed, calls generator function
 * associated with the configured property and adds it to the DBO execution
 * context as a generared param using the property path as the param name.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @implements module:x2node-dbos.DBOCommand
 */
class GeneratorCommand {

	/**
	 * Create new command.
	 *
	 * @param {module:x2node-records~PropertyDescriptor} propDesc Generated
	 * property descriptor.
	 */
	constructor(propDesc) {

		this._propDesc = propDesc;
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		const propDesc = this._propDesc;
		const propPath = propDesc.container.nestedPath + propDesc.name;
		return promiseChain.then(
			() => {
				try {

					const val = propDesc.generator(ctx.connection);

					if (val instanceof Promise)
						return val.then(
							resVal => {
								ctx.addGeneratedParam(propPath, resVal);
							},
							err => {
								common.error(
									`error generating property ${propPath}` +
										` value`, err);
								return Promise.reject(err);
							}
						);

					ctx.addGeneratedParam(propPath, val);

				} catch (err) {
					common.error(
						`error generating property ${propPath} value`, err);
					return Promise.reject(err);
				}
			},
			err => Promise.reject(err)
		);
	}
}

/**
 * Assigned id command. When executed, takes the property value from the provided
 * record data and adds it to the DBO execution context as a generared param
 * using the property path as the param name.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @implements module:x2node-dbos.DBOCommand
 */
class AssignedIdCommand {

	/**
	 * Create new command.
	 *
	 * @param {module:x2node-records~PropertyDescriptor} propDesc Id property
	 * descriptor.
	 * @param {Object} data The object data.
	 */
	constructor(propDesc, data) {

		this._propDesc = propDesc;
		this._idVal = data[propDesc.name];

		if ((this._idVal === undefined) || (this._idVal === null))
			throw new common.X2UsageError(
				`No value provided for non-generated id property ` +
					`${propDesc.container.nestedPath}${propDesc.name}.`);
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		return promiseChain.then(
			() => {
				ctx.addGeneratedParam(
					this._propDesc.container.nestedPath + this._propDesc.name,
					this._idVal
				);
			},
			err => Promise.reject(err)
		);
	}
}

/**
 * SQL INSERT statement command. When executed, builds a SQL
 * INSERT statement for the configured table using column/value
 * pairs added to the command and executes the statement.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @implements module:x2node-dbos.DBOCommand
 */
class InsertCommand {

	/**
	 * Create new command.
	 *
	 * @param {string} table The table.
	 */
	constructor(table) {

		this._table = table;

		this._columns = new Array();
		this._values = new Array();
	}

	/**
	 * Add column/value pair to the statement's SET clause.
	 *
	 * @param {string} column Column name.
	 * @param {string} value Value SQL expression.
	 */
	add(column, value) {

		this._columns.push(column);
		this._values.push(value);
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		const stmt = this._buildStatement();

		return promiseChain.then(
			() => new Promise((resolve, reject) => {
				let sql;
				try {
					sql = ctx.replaceParams(stmt);
					ctx.log(`executing SQL: ${sql}`);
					ctx.dbDriver.executeInsert(
						ctx.connection, sql, {
							onSuccess() {
								resolve();
							},
							onError(err) {
								common.error(
									`error executing SQL [${sql}]`, err);
								reject(err);
							}
						});
				} catch (err) {
					common.error(`error executing SQL [${sql || stmt}]`, err);
					reject(err);
				}
			}),
			err => Promise.reject(err)
		);
	}

	/**
	 * Build SQL INSERT statement.
	 *
	 * @protected
	 * @returns {string} The SQL statement (may contain param placeholders).
	 */
	_buildStatement() {

		return 'INSERT INTO ' + this._table + ' (' +
			this._columns.join(', ') + ') VALUES (' +
			this._values.join(', ') + ')';
	}
}

/**
 * SQL INSERT statement with auto-generated id command. Similar to
 * {module:x2node-dbos~InsertCommand}, but upon execution sets the generated by
 * the database id value for the new record or nested object into the record
 * object and also adds it to the DBO execution context as a generared param
 * using the id property path as the param name.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @extends module:x2node-dbos~InsertCommand
 */
class InsertWithGeneratedIdCommand extends InsertCommand {

	/**
	 * Create new command.
	 *
	 * @param {string} table The table.
	 * @param {module:x2node-records~PropertyDescriptor} propDesc Auto-generated
	 * id property descriptor.
	 * @param {Object} obj Object, into which to set the generated id property
	 * after the command is executed.
	 */
	constructor(table, propDesc, obj) {
		super(table);

		this._propDesc = propDesc;
		this._obj = obj;
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		const stmt = this._buildStatement();

		const propDesc = this._propDesc;
		const propPath = propDesc.container.nestedPath + propDesc.name;
		const obj = this._obj;
		return promiseChain.then(
			() => new Promise((resolve, reject) => {
				let sql;
				try {
					sql = ctx.replaceParams(stmt);
					ctx.log(`executing SQL: ${sql}`);
					ctx.dbDriver.executeInsert(
						ctx.connection, sql, {
							onSuccess(rawId) {
								const id = rsparser.extractValue(
									propDesc.scalarValueType, rawId);
								obj[propDesc.name] = id;
								ctx.addGeneratedParam(propPath, id);
								resolve();
							},
							onError(err) {
								common.error(
									`error executing SQL [${sql}]`, err);
								reject(err);
							}
						}, propDesc.column);
				} catch (err) {
					common.error(`error executing SQL [${sql || stmt}]`, err);
					reject(err);
				}
			}),
			err => Promise.reject(err)
		);
	}
}

/**
 * Update entangled records command executed at the end of the DBO. When
 * executed, the command takes the updated entangled records information from the
 * DBO execution context, generates the appropriate SQL UPDATE
 * statements and executes them.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @implements module:x2node-dbos.DBOCommand
 */
class UpdateEntangledRecordsCommand {

	constructor(updatedRecordTypeNames) {

		this._updatedRecordTypeNames = updatedRecordTypeNames;
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		return promiseChain.then(
			() => {

				// pre-resolve the completion promise
				let resPromise = Promise.resolve();

				// go over entangled record types and generate the updates
				const sets = new Array();
				for (let recordTypeName in ctx.entangledUpdates) {

					// get the entangled record ids
					const ids = ctx.entangledUpdates[recordTypeName];
					if (ids.size === 0)
						continue;

					// get record type descriptor
					const recordTypeDesc = ctx.recordTypes.getRecordTypeDesc(
						recordTypeName);

					// check if has anything to update and build SET clause
					getModificationMetaInfoSets(sets, recordTypeDesc);
					if (sets.length === 0)
						continue;

					// register record type update
					if (this._updatedRecordTypeNames)
						this._updatedRecordTypeNames.add(recordTypeName);

					// build the UPDATE statement
					const idColumn = recordTypeDesc.getPropertyDesc(
						recordTypeDesc.idPropertyName).column;
					const stmt =
						'UPDATE ' + recordTypeDesc.table + ' SET ' + sets.map(
							s => `${s.columnName} = ${s.value}`).join(', ') +
						' WHERE ' + (
							ids.size === 1 ?
								idColumn + ' = ' + ctx.dbDriver.sql(
									ids.values().next().value) :
								idColumn + ' IN (' + Array.from(ids).map(
									v => ctx.dbDriver.sql(v)).join(', ') + ')'
						);

					// queue up UPDATE statement execution
					resPromise = resPromise.then(
						() => new Promise((resolve, reject) => {
							let sql;
							try {
								sql = ctx.replaceParams(stmt);
								ctx.log(`executing SQL: ${sql}`);
								ctx.dbDriver.executeUpdate(ctx.connection, sql, {
									onSuccess() {
										resolve();
									},
									onError(err) {
										common.error(
											`error executing SQL [${sql}]`, err);
										reject(err);
									}
								});
							} catch (err) {
								common.error(
									`error executing SQL [${sql || stmt}]`, err);
								reject(err);
							}
						}),
						err => Promise.reject(err)
					);
				}

				// return the completion promise
				return resPromise;
			},
			err => Promise.reject(err)
		);
	}
}

/**
 * Symbol used to store a set on the transaction that keeps track of modification
 * of what record collections has been already reported to the monitor during
 * transaction.
 *
 * @private
 */
const UPDATED_COLLECTIONS = Symbol('UPDATED_COLLECTIONS');

/**
 * Call record collections monitor and notify it about a record collections
 * update.
 *
 * @private
 * @memberof module:x2node-dbos
 * @inner
 * @implements module:x2node-dbos.DBOCommand
 */
class NotifyRecordCollectionsMonitorCommand {

	constructor(monitor, recordTypeNames) {

		this._monitor = monitor;
		this._recordTypeNames = recordTypeNames;
	}

	// add command execution to the chain
	queueUp(promiseChain, ctx) {

		if (!this._monitor)
			return promiseChain;

		return promiseChain.then(() => {
			let updatedCollections = ctx.transaction[UPDATED_COLLECTIONS];
			if (!updatedCollections) {
				updatedCollections = ctx.transaction[UPDATED_COLLECTIONS] =
					new Set();
			}
			const namesToAdd = new Set();
			for (let name of this._recordTypeNames) {
				if (!updatedCollections.has(name)) {
					updatedCollections.add(name);
					namesToAdd.add(name);
				}
			}
			if (namesToAdd.size > 0)
				return this._monitor.collectionsUpdated(ctx, namesToAdd);
		});
	}
}

/////////////////////////////////////////////////////////////////////////////////
// THE ABSTRACT DBO
/////////////////////////////////////////////////////////////////////////////////

/**
 * Get elements of an UPDATE statement's SET clause for updating record
 * modification meta-info.
 *
 * @function module:x2node-dbos~AbstractDBO.getModificationMetaInfoSets
 * @param {Array} [sets] Array to use for the SET clause elements. If provided,
 * it is cleared before adding the SET clause elements. If not provided, a new
 * array is created.
 * @param {module:x2node-records~RecordTypeDescriptor} recordTypeDesc Record type
 * descriptor.
 * @param {string} [tableAlias] Alias of the record type main table in the UPDATE
 * statement, or nothing is not used.
 * @returns {Array} SET clause elements, or empty array is no record modification
 * meta-info on the record type.
 */
function getModificationMetaInfoSets(sets, recordTypeDesc, tableAlias) {

	if (sets)
		sets.length = 0;
	else
		sets = new Array();

	let propName = recordTypeDesc.getRecordMetaInfoPropName('version');
	if (propName) {
		const column = recordTypeDesc.getPropertyDesc(propName).column;
		sets.push({
			columnName: column,
			value: (tableAlias ? tableAlias + '.' : '') + column + ' + 1'
		});
	}

	propName = recordTypeDesc.getRecordMetaInfoPropName('modificationTimestamp');
	if (propName)
		sets.push({
			columnName: recordTypeDesc.getPropertyDesc(propName).column,
			value: '?{ctx.executedOn}'
		});

	propName = recordTypeDesc.getRecordMetaInfoPropName('modificationActor');
	if (propName)
		sets.push({
			columnName: recordTypeDesc.getPropertyDesc(propName).column,
			value: '?{ctx.actor}'
		});

	return sets;
}

/**
 * Abstract database operation implementation.
 *
 * @protected
 * @memberof module:x2node-dbos
 * @inner
 * @abstract
 */
class AbstractDBO {

	/**
	 * Create new DBO.
	 *
	 * @constructor
	 * @param {module:x2node-dbos.DBDriver} dbDriver The database driver.
	 * @param {module:x2node-records~RecordTypesLibrary} recordTypes Record types
	 * library.
	 * @param {module:x2node-dbos.RecordCollectionsMonitor} [rcMonitor] The
	 * record collections monitor.
	 */
	constructor(dbDriver, recordTypes, rcMonitor) {

		/**
		 * Database driver.
		 *
		 * @protected
		 * @member {module:x2node-dbos.DBDriver} module:x2node-dbos~AbstractDBO#_dbDriver
		 */
		this._dbDriver = dbDriver;

		/**
		 * The record types library.
		 *
		 * @protected
		 * @member {module:x2node-records~RecordTypesLibrary} module:x2node-dbos~AbstractDBO#_recordTypes
		 */
		this._recordTypes = recordTypes;

		this._rcMonitor = rcMonitor;
		this._updatedRecordTypeNames = (rcMonitor ? new Set() : null);

		/**
		 * Debug logger.
		 *
		 * @protected
		 * @member {function} module:x2node-dbos~AbstractDBO#_log
		 */
		this._log = common.getDebugLogger('X2_DBO');

		/**
		 * Filter parameters handler.
		 *
		 * @protected
		 * @member {module:x2node-dbos~FilterParamsHandler} module:x2node-dbos~AbstractDBO#_paramsHandler
		 */
		this._paramsHandler = new FilterParamsHandler();

		/**
		 * Tells if actor is required for the DBO execution. Initially is set to
		 * false allowing anonymous DBO executions.
		 *
		 * @protected
		 * @member {boolean} module:x2node-dbos~AbstractDBO#_actorRequired
		 */
		this._actorRequired = false;
	}

	/////////////////////////////////////////////////////////////////////////////
	// DBO commands construction helper methods
	/////////////////////////////////////////////////////////////////////////////

	// make it a static class function so it gets exported
	static getModificationMetaInfoSets(sets, recordTypeDesc, tableAlias) {

		return getModificationMetaInfoSets(sets, recordTypeDesc, tableAlias);
	}

	/**
	 * Build a DBO command that simply executes the specified SQL statement. The
	 * command also calls context's
	 * [affectedRows()]{@link module:x2node-dbos~DBOExecutionContext#affectedRows}
	 * method upon completion.
	 *
	 * @protected
	 * @param {string} stmt The SQL statement (may contain param placeholders).
	 * @param {*} [stmtId] DBO-specific statement id, if any.
	 * @returns {module:x2node-dbos.DBOCommand} The command.
	 */
	_createExecuteStatementCommand(stmt, stmtId) {

		return new ExecuteStatementCommand(stmt, stmtId);
	}

	/**
	 * Build a DBO command that loads record ids into a temporary anchor table
	 * used for multi-branch fetches. The anchor table name is available on the
	 * resulting command. The table has two columns: "id" and "ord".
	 *
	 * @protected
	 * @param {module:x2node-dbos~QueryTreeNode} idsQueryTree Query tree for the
	 * record ids.
	 * @param {?module:x2node-dbos~RecordsFilter} [filter] Optional filter for
	 * the ids SELECT query.
	 * @param {?module:x2node-dbos~RecordsOrder} [order] Optional order for the
	 * ids SELECT query.
	 * @param {?module:x2node-dbos~RecordsRange} [range] Optional range for the
	 * ids SELECT query.
	 * @param {?string} [lockType] Optional lock type: "exclusive" or "shared".
	 * @returns {module:x2node-dbos.DBOCommand} The command.
	 */
	_createLoadAnchorTableCommand(idsQueryTree, filter, order, range, lockType) {

		const idsQuery = this._assembleSelect(idsQueryTree, filter, order);

		let idsQuerySql = idsQuery.toSql(true);

		if (range)
			idsQuerySql = this._dbDriver.makeRangedSelect(
				idsQuerySql, range.offset, range.limit);

		if (lockType) {
			const exclusiveLockTables = new Array();
			const sharedLockTables = new Array();
			idsQuery.getTablesForLock(
				lockType, exclusiveLockTables, sharedLockTables);
			idsQuerySql = this._dbDriver.makeSelectWithLocks(
				idsQuerySql, exclusiveLockTables, sharedLockTables);
		}

		return new LoadAnchorTableCommand(
			idsQueryTree.table, idsQueryTree.keyColumn,
			idsQuery.getIdValueExpr(), idsQuerySql);
	}

	/**
	 * Assemble a SELECT query.
	 *
	 * @protected
	 * @param {module:x2node-dbos~QueryTreeNode} idsQueryTree Query tree.
	 * @param {?module:x2node-dbos~RecordsFilter} [filter] Optional filter.
	 * @param {?module:x2node-dbos~RecordsOrder} [order] Optional order.
	 * @returns {module:x2node-dbos~SelectQuery} The query builder.
	 */
	_assembleSelect(queryTree, filter, order) {

		return selectQueryBuilder.assembleSelect(
			queryTree, queryTree.getTopTranslationContext(this._paramsHandler),
			filter, order);
	}

	/**
	 * Build DBO commands used to insert records and values and add them to the
	 * provided commands sequence.
	 *
	 * @protected
	 * @param {Array.<module:x2node-dbos.DBOCommand>} commands The commands
	 * sequence, to which to add the insert commands.
	 * @param {string} table The table.
	 * @param {?string} parentIdColumn Parent id column, or null for
	 * the top record type table.
	 * @param {string} [parentIdPropPath] If parentIdColumn is
	 * provided, this is the path to the id property in the parent container.
	 * @param {module:x2node-records~PropertyDescriptor} [colPropDesc] If
	 * commands are created for inserting nested objects into a nested object
	 * array or map property, then this is the array or the map property
	 * descriptor.
	 * @param {(number|string)} [keyVal] Array element index or map key value if
	 * colPropDesc is provided.
	 * @param {module:x2node-records~PropertiesContainer} container Top container
	 * for the table.
	 * @param {Object} data Object matching the container.
	 */
	_createInsertCommands(
		commands, table, parentIdColumn, parentIdPropPath, colPropDesc, keyVal,
		container, data) {

		// create insert command
		let insertCmd, idPropPath;
		if (container.idPropertyName) {
			const idPropDesc = container.getPropertyDesc(
				container.idPropertyName);
			idPropPath = idPropDesc.container.nestedPath + idPropDesc.name;
			if (idPropDesc.isGenerated()) {
				if (idPropDesc.generator === 'auto') {
					insertCmd = new InsertWithGeneratedIdCommand(
						table, idPropDesc, data);
				} else { // generator function
					commands.push(new GeneratorCommand(idPropDesc));
					insertCmd = new InsertCommand(table);
					insertCmd.add(idPropDesc.column, '?{' + idPropPath + '}');
				}
			} else {
				commands.push(new AssignedIdCommand(idPropDesc, data));
				insertCmd = new InsertCommand(table);
				insertCmd.add(idPropDesc.column, '?{' + idPropPath + '}');
			}
		} else {
			insertCmd = new InsertCommand(table);
			idPropPath = parentIdPropPath;
		}

		// add parent id column
		if (parentIdColumn)
			insertCmd.add(parentIdColumn, '?{' + parentIdPropPath + '}');

		// add array element index column
		if (colPropDesc && colPropDesc.isArray() && colPropDesc.indexColumn)
			insertCmd.add(
				colPropDesc.indexColumn, this._dbDriver.sql(keyVal));

		// add map key column
		if (colPropDesc && colPropDesc.isMap() && colPropDesc.keyColumn)
			insertCmd.add(
				colPropDesc.keyColumn, this._makeMapKeySql(colPropDesc, keyVal));

		// add record meta-info properties
		if (container.isRecordType()) {
			let propName = container.getRecordMetaInfoPropName('version');
			if (propName)
				insertCmd.add(
					container.getPropertyDesc(propName).column,
					'1'
				);
			propName = container.getRecordMetaInfoPropName('creationTimestamp');
			if (propName)
				insertCmd.add(
					container.getPropertyDesc(propName).column,
					'?{ctx.executedOn}'
				);
			propName = container.getRecordMetaInfoPropName('creationActor');
			if (propName) {
				this._actorRequired = true;
				insertCmd.add(
					container.getPropertyDesc(propName).column,
					'?{ctx.actor}'
				);
			}
		}

		// process the container properties
		this._createInsertCommandsForContainer(
			commands, commands.push(insertCmd) - 1, idPropPath, container, data);
	}

	/**
	 * Process record, add columns to the insert command and recursively add
	 * dependent inserts to the sequence.
	 *
	 * @private
	 * @param {Array.<module:x2node-dbos.DBOCommand>} commands The commands
	 * sequence, to which to add the insert commands.
	 * @param {number} insertCmdInd Index of the current insert command in the
	 * commands sequence.
	 * @param {string} idPropPath Property path of the id in the current insert
	 * command.
	 * @param {module:x2node-records~PropertiesContainer} container Container
	 * descriptor with the properties to add.
	 * @param {Object} data Object matching the container.
	 * @returns {number} The current insert command index in the sequence, which
	 * may have been changed by the method (generators could have been inserted
	 * before the command shifting it down the sequence).
	 */
	_createInsertCommandsForContainer(
		commands, insertCmdInd, idPropPath, container, data) {

		// get the current insert command
		const insertCmd = commands[insertCmdInd];

		// go over the container properties
		for (let propName of container.allPropertyNames) {
			const propDesc = container.getPropertyDesc(propName);

			// skip properties we don't need to insert
			if (propDesc.isCalculated() || propDesc.isId() ||
				propDesc.isRecordMetaInfo() || propDesc.isView() ||
				propDesc.reverseRefPropertyName)
				continue;

			// get the value
			const propVal = data[propName];

			// check if nested object
			if (propDesc.scalarValueType === 'object') {

				// check if there is a value
				if ((propVal === undefined) || (propVal === null)) {
					if (!propDesc.optional)
						throw new common.X2UsageError(
							'No value provided for required property ' +
								container.nestedPath + propName + '.');
					continue;
				}

				// process depending on the structural type
				if (propDesc.isArray()) {

					// check the type
					if (!Array.isArray(propVal))
						new common.X2UsageError(
							'Invalid value type for property ' +
								container.nestedPath + propName +
								', expected an array.');

					// check if empty
					if (propVal.length === 0) {
						if (!propDesc.optional)
							throw new common.X2UsageError(
								'No value provided for required property ' +
									container.nestedPath + propName + '.');
						continue;
					}

					// add the inserts
					propVal.forEach((v, i) => {
						if ((v === undefined) || (v === null) ||
							((typeof v) !== 'object') || Array.isArray(v))
							new common.X2UsageError(
								'Invalid array element for property ' +
									container.nestedPath + propName +
									', expected an object.');
						this._createInsertCommands(
							commands, propDesc.table, propDesc.parentIdColumn,
							idPropPath, propDesc, i, propDesc.nestedProperties,
							v);
					});

				} else if (propDesc.isMap()) {

					// check the type
					if (((typeof propVal) !== 'object') ||
						Array.isArray(propVal))
						new common.X2UsageError(
							'Invalid value type for property ' +
								container.nestedPath + propName +
								', expected an object.');

					// check if empty
					const keys = Object.keys(propVal);
					if (keys.length === 0) {
						if (!propDesc.optional)
							throw new common.X2UsageError(
								'No value provided for required property ' +
									container.nestedPath + propName + '.');
						continue;
					}

					// add the inserts
					keys.forEach(key => {
						const v = propVal[key];
						if ((v === undefined) || (v === null) ||
							((typeof v) !== 'object') || Array.isArray(v))
							new common.X2UsageError(
								'Invalid map element for property ' +
									container.nestedPath + propName +
									', expected an object.');
						this._createInsertCommands(
							commands, propDesc.table, propDesc.parentIdColumn,
							idPropPath, propDesc, key, propDesc.nestedProperties,
							v);
					});

				} else {

					// check the type
					if (((typeof propVal) !== 'object') ||
						Array.isArray(propVal))
						new common.X2UsageError(
							'Invalid value type for property ' +
								container.nestedPath + propName +
								', expected an object.');

					// check if in a separate table
					if (propDesc.table) {
						this._createInsertCommands(
							commands, propDesc.table, propDesc.parentIdColumn,
							idPropPath, null, null, propDesc.nestedProperties,
							propVal);
					} else {
						insertCmdInd = this._createInsertCommandsForContainer(
							commands, insertCmdInd, idPropPath,
							propDesc.nestedProperties, propVal);
					}
				}

			} else { // simple value or ref

				// value SQL to add to the insert
				let propValSql;

				// check if generated and no value
				if ((propVal === undefined) && propDesc.isGenerated()) {

					// skip if auto-generated
					if (propDesc.generator === 'auto')
						continue;

					// add generator command
					commands.splice(
						insertCmdInd++, 0, new GeneratorCommand(propDesc));
					propValSql = '?{' + propDesc.container.nestedPath +
						propDesc.name + '}';

				} else if ((propVal !== undefined) && (propVal !== null)) {
					if (propDesc.isArray()) {
						if (!Array.isArray(propVal))
							new common.X2UsageError(
								'Invalid value type for property ' +
									container.nestedPath + propName +
									', expected an array.');
						if (propVal.length > 0)
							propValSql = propVal.map(
								v => this._makePropValSql(propDesc, v));
					} else if (propDesc.isMap()) {
						if (((typeof propVal) !== 'object') ||
							Array.isArray(propVal))
							new common.X2UsageError(
								'Invalid value type for property ' +
									container.nestedPath + propName +
									', expected an object.');
						const keys = Object.keys(propVal);
						if (keys.length > 0) {
							propValSql = keys.reduce((res, k) => {
								res.set(k, this._makePropValSql(
									propDesc, propVal[k]));
								return res;
							}, new Map());
						}
					} else {
						propValSql = this._makePropValSql(propDesc, propVal);
					}
				}

				// check if no value
				if (propValSql === undefined) {
					if (!propDesc.optional)
						throw new common.X2UsageError(
							'No value provided for required property ' +
								container.nestedPath + propName + '.');
					continue;
				}

				// make the corresponding inserts
				if (propDesc.table) {
					const idSql = '?{' + idPropPath + '}';
					if (propDesc.isArray()) {
						propValSql.forEach((v, i) => {
							const valInsert = new InsertCommand(propDesc.table);
							valInsert.add(propDesc.parentIdColumn, idSql);
							if (propDesc.indexColumn)
								valInsert.add(
									propDesc.indexColumn, this._dbDriver.sql(i));
							valInsert.add(propDesc.column, v);
							commands.push(valInsert);
						});
					} else if (propDesc.isMap()) {
						propValSql.forEach((v, k) => {
							const valInsert = new InsertCommand(propDesc.table);
							valInsert.add(propDesc.parentIdColumn, idSql);
							if (propDesc.keyColumn)
								valInsert.add(
									propDesc.keyColumn,
									this._makeMapKeySql(propDesc, k)
								);
							valInsert.add(propDesc.column, v);
							commands.push(valInsert);
						});
					} else {
						const valInsert = new InsertCommand(propDesc.table);
						valInsert.add(propDesc.parentIdColumn, idSql);
						valInsert.add(propDesc.column, propValSql);
						commands.push(valInsert);
					}
				} else {
					insertCmd.add(propDesc.column, propValSql);
				}
			}
		}

		// go over subtype-specific properties if polymorph object
		if (container.isPolymorphObject()) {

			// get the subtype
			const subtypeName = data[container.typePropertyName];
			if ((typeof subtypeName) !== 'string')
				throw new common.X2UsageError(
					'Type property of polymorphic ' + (
							container.isRecordType() ?
								'record' :
								'property ' + container.nestedPath
						) + ' is missing or is not a string.');

			// get the subtype extension container
			if (!container.hasProperty(subtypeName))
				throw new common.X2UsageError(
					'Unknown type "' + subtypeName + '" of polymorphic ' + (
							container.isRecordType() ?
								'record' :
								'property ' + container.nestedPath
						) + '.');
			const subtypeDesc = container.getPropertyDesc(subtypeName);
			if (!subtypeDesc.isSubtype())
				throw new common.X2UsageError(
					'Unknown type "' + subtypeName + '" of polymorphic ' + (
							container.isRecordType() ?
								'record' :
								'property ' + container.nestedPath
						) + '.');

			// add type column to the insert if any
			const typePropDesc = container.getPropertyDesc(
				container.typePropertyName);
			if (typePropDesc.column)
				insertCmd.add(
					typePropDesc.column, this._dbDriver.sql(subtypeName));

			// add insert commands for the subtype-specific properties
			if (subtypeDesc.table) {
				this._createInsertCommands(
					commands, subtypeDesc.table, subtypeDesc.parentIdColumn,
					idPropPath, null, null, subtypeDesc.nestedProperties, data);
			} else {
				insertCmdInd = this._createInsertCommandsForContainer(
					commands, insertCmdInd, idPropPath,
					subtypeDesc.nestedProperties, data);
			}
		}

		// TODO: support polymorphic reference container

		// return the insert command index
		return insertCmdInd;
	}

	/**
	 * Validate property value and make SQL for it.
	 *
	 * @protected
	 * @param {module:x2node-records~PropertyDescriptor} propDesc Property
	 * descriptor.
	 * @param {*} val Property value. If null or
	 * undefined, SQL NULL is returned.
	 * @returns {string} The value SQL.
	 * @throws {module:x2node-common.X2UsageError} If the value is not good.
	 */
	_makePropValSql(propDesc, val) {

		if ((val === null) || (val === undefined))
			return this._dbDriver.sql(null);

		const valSql = this._valueToSql(
			val, propDesc.scalarValueType, propDesc.refTarget,
			expectedType => new common.X2UsageError(
				'Invalid value type [' + (typeof val) + '] for property ' +
					propDesc.container.nestedPath + propDesc.name +
					', expected [' + expectedType + '].')
		);

		if (valSql === null)
			throw new common.X2UsageError(
				'Invalid value [' + String(val) + '] for property ' +
					propDesc.container.nestedPath +  propDesc.name + '.');

		return valSql;
	}

	/**
	 * Validate value for a map property key and make SQL for it. The method is
	 * also capable of converting the key value from string to the expected key
	 * value type (relevant for "number" and "boolean" types).
	 *
	 * @protected
	 * @param {module:x2node-records~PropertyDescriptor} mapPropDesc Map property
	 * descriptor.
	 * @param {*} key Key value. May not be null or
	 * undefined.
	 * @returns {string} The key value SQL.
	 * @throws {module:x2node-common.X2UsageError} If the key value is not good.
	 */
	_makeMapKeySql(mapPropDesc, key) {

		const invalidKeyVal = () => new common.X2UsageError(
			`Invalid key value [${String(key)}] for map property ` +
				`${mapPropDesc.container.nestedPath}${mapPropDesc.name}.`);

		if ((key === null) || (key === undefined))
			throw invalidKeyVal();

		let keyToUse;
		if ((typeof key) === 'string') {
			switch (mapPropDesc.keyValueType) {
			case 'number':
				keyToUse = Number(key);
				break;
			case 'boolean':
				keyToUse = (
					key === 'true' ? true : (key === 'false' ? false : null));
				break;
			default:
				keyToUse = key;
			}
		}

		const keySql = this._valueToSql(
			keyToUse, mapPropDesc.keyValueType, mapPropDesc.keyRefTarget,
			expectedType => new common.X2UsageError(
				`Invalid key value type [${typeof key}] for map property ` +
					`${mapPropDesc.container.nestedPath}${mapPropDesc.name},` +
					` expected [${expectedType}].`)
		);

		if (keySql === null)
			throw invalidKeyVal();

		return keySql;
	}

	/**
	 * Validate value against expected value type and convert it into SQL value
	 * expression.
	 *
	 * @private
	 * @param {*} val The value.
	 * @param {string} valueType Scalar value type.
	 * @param {string} [expectedRefTarget] If expected value type is "ref", then
	 * this is expected target record type name.
	 * @param {function} invalidValType Function to use to create throwable error
	 * when the specified value's ES type does not match the specified expected
	 * value type. The function takes the expected ES type as an argument.
	 * @returns {string} SQL value expression, or null if the value
	 * is invalid, including null and undefined.
	 */
	_valueToSql(val, valueType, expectedRefTarget, invalidValType) {

		let valSql = null;
		let hashInd;
		switch (valueType) {
		case 'string':
			if ((typeof val) !== 'string')
				throw invalidValType('string');
			valSql = this._dbDriver.stringLiteral(val);
			break;
		case 'number':
			if ((typeof val) !== 'number')
				throw invalidValType('number');
			valSql = this._dbDriver.sql(val);
			break;
		case 'boolean':
			if ((typeof val) !== 'boolean')
				throw invalidValType('boolean');
			valSql = this._dbDriver.booleanLiteral(val);
			break;
		case 'datetime':
			if (val instanceof Date) {
				valSql = this._dbDriver.datetimeLiteral(val);
			} else if ((typeof val) === 'string') {
				if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(val)) {
					const dateVal = Date.parse(val);
					if (!Number.isNaN(dateVal))
						valSql = this._dbDriver.datetimeLiteral(
							new Date(dateVal));
				}
			} else {
				throw invalidValType('string or Date');
			}
			break;
		case 'ref':
			if ((typeof val) !== 'string')
				throw invalidValType('string');
			hashInd = val.indexOf('#');
			if ((hashInd > 0) && (hashInd < val.length - 1)) {
				const refTarget = val.substring(0, hashInd);
				if (refTarget === expectedRefTarget) {
					const refTargetDesc = this._recordTypes.getRecordTypeDesc(
						refTarget);
					const refIdPropDesc = refTargetDesc.getPropertyDesc(
						refTargetDesc.idPropertyName);
					valSql = this._dbDriver.sql(
						refIdPropDesc.scalarValueType === 'number' ?
							Number(val.substring(hashInd + 1)) :
							val.substring(hashInd + 1)
					);
				}
			}
		}

		return valSql;
	}

	/**
	 * Build DBO command used to update entangled records modification meta-info
	 * at the end of the DBO. The updated entangled records information is taken
	 * from the DBO execution context's
	 * [entangledUpdates]{@link module:x2node-dbos~DBOExecutionContext#entangledUpdates}
	 * property.
	 *
	 * @protected
	 * @returns {module:x2node-dbos.DBOCommand} The command.
	 */
	_createUpdateEntangledRecordsCommand() {

		return new UpdateEntangledRecordsCommand(this._updatedRecordTypeNames);
	}

	/**
	 * Build DBO command that notifies registered record collections monitor
	 * about the updated record types. The record type names are registered by
	 * the DBO throughout its execution via the
	 * [_registerRecordTypeUpdate()]{@link module:x2node-dbos~AbstractDBO#_registerRecordTypeUpdate}
	 * method.
	 *
	 * @protected
	 * @returns {module:x2node-dbos.DBOCommand} The command.
	 */
	_createNotifyRecordCollectionsMonitorCommand() {

		return new NotifyRecordCollectionsMonitorCommand(
			this._rcMonitor, this._updatedRecordTypeNames);
	}

	/////////////////////////////////////////////////////////////////////////////
	// DBO execution helper methods
	/////////////////////////////////////////////////////////////////////////////

	/**
	 * Register an update of a record of the specified record type.
	 *
	 * @protected
	 * @param {string} recordTypeName Updated record type name.
	 */
	_registerRecordTypeUpdate(recordTypeName) {

		if (this._updatedRecordTypeNames)
			this._updatedRecordTypeNames.add(recordTypeName);
	}

	/**
	 * Execute DBO commands.
	 *
	 * @protected
	 * @param {module:x2node-dbos~DBOExecutionContext} ctx The operation
	 * execution context.
	 * @returns {Promise} Operation result promise.
	 */
	_executeCommands(ctx) {

		// check if actor is required
		if (this._actorRequired && !ctx.actor)
			throw new common.X2UsageError('Operation may not be anonymous.');

		// initial pre-resolved result promise for the chain
		let resPromise = Promise.resolve();

		// start transaction if necessary
		if (ctx.wrapInTx)
			resPromise = this._startTx(resPromise, ctx);

		// queue up the commands
		this._commands.forEach(cmd => {
			resPromise = cmd.queueUp(resPromise, ctx);
		});

		// finish transaction if necessary
		if (ctx.wrapInTx)
			resPromise = this._endTx(resPromise, ctx);

		// build the final result object
		resPromise = resPromise.then(() => ctx.getResult());

		// return the result promise chain
		return resPromise;
	}

	/**
	 * Add transaction start to the operation execution promise chain.
	 *
	 * @private
	 * @param {Promise} promiseChain The promise chain.
	 * @param {module:x2node-dbos~DBOExecutionContext} ctx The operation
	 * execution context.
	 * @returns {Promise} The promise chain with the transaction operation added.
	 */
	_startTx(promiseChain, ctx) {

		return promiseChain.then(
			() => {
				try {
					return ctx.transaction.start();
				} catch (err) {
					common.error('error starting transaction', err);
					return Promise.reject(err);
				}
			}
		);
	}

	/**
	 * Add transaction end to the operation execution promise chain.
	 *
	 * @private
	 * @param {Promise} promiseChain The promise chain.
	 * @param {module:x2node-dbos~DBOExecutionContext} ctx The operation
	 * execution context.
	 * @returns {Promise} The promise chain with the transaction operation added.
	 */
	_endTx(promiseChain, ctx) {

		const rollbackAfterFailedCommit = err => new Promise((resolve, reject) => {
			this._log('rolling back transaction after failed commit');
			this._dbDriver.rollbackTransaction(ctx.connection, {
				onSuccess() {
					reject(err);
				},
				onError(rollbackErr) {
					common.error(
						'error rolling transaction back after' +
							' failed commit', rollbackErr);
					reject(err);
				}
			});
		});

		return promiseChain.then(
			() => {
				try {
					return ctx.transaction.commit().catch(err => {
						return rollbackAfterFailedCommit(err);
					});
				} catch (err) {
					common.error('error committing transaction', err);
					return rollbackAfterFailedCommit(err);
				}
			},
			err => {
				if (ctx.rollbackOnError) {
					try {
						return ctx.transaction.rollback().then(
							() => Promise.reject(err),
							rollbackErr => {
								common.error(
									'error rolling transaction back',
									rollbackErr);
								return Promise.reject(err);
							}
						);
					} catch (rollbackErr) {
						common.error(
							'error rolling transaction back', rollbackErr);
						return Promise.reject(err);
					}
				} else {
					return Promise.reject(err);
				}
			}
		);
	}

	/**
	 * Replace parameter placeholders in the specified SQL statement with the
	 * corresponding values.
	 *
	 * @protected
	 * @param {string} stmt SQL statement text with parameter placeholders. Each
	 * placeholder has format "?{ref}" where "ref" is the parameter reference in
	 * the operation's records filter parameters handler.
	 * @param {module:x2node-dbos~DBOExecutionContext} ctx The operation
	 * execution context. The method uses context's
	 * [getParamSql()]{@link module:x2node-dbos~DBOExecutionContext#getParamSql}
	 * method to get values for the parameter placeholders.
	 * @returns {string} Ready to execute SQL statement with parameter
	 * placeholders replaced.
	 */
	_replaceParams(stmt, ctx) {

		let res = '';

		const re = new RegExp('(\'(?!\'))|(\')|\\?\\{([^}]+)\\}', 'g');
		let m, inLiteral = false, lastMatchIndex = 0;
		while ((m = re.exec(stmt)) !== null) {
			res += stmt.substring(lastMatchIndex, m.index);
			lastMatchIndex = re.lastIndex;
			const s = m[0];
			if (inLiteral) {
				res += s;
				if (m[1]) {
					inLiteral = false;
				} else if (m[2]) {
					re.lastIndex++;
				}
			} else {
				if (s === '\'') {
					res += s;
					inLiteral = true;
				} else {
					res += ctx.getParamSql(m[3]);
				}
			}
		}
		res += stmt.substring(lastMatchIndex);

		return res;
	}
}

// export the class
module.exports = AbstractDBO;


text:
Function.RegisterNamespace("Test.Aura");

[Fixture]
Test.Aura.AuraComponentServiceTest = function(){
    var $A = {
        assert: function(condition, message) {
            if (!condition) {
                var error = new Error(message);
                throw error;
            }
        },
        util: {
            isFunction: function(obj){
                return false;
            }
        }
    };
    var Aura = {
        Services: {},
        Component: {
            ComponentDefStorage: function () {}
        },
        Library: {
            LibraryDefRegistry: function () {},
        }
    };

    Mocks.GetMocks(Object.Global(), {
        "AuraComponentService": function(){},
        "ComponentDefStorage": function(){},
        "Aura": Aura
    })(function(){
        [Import("aura-impl/src/main/resources/aura/component/ComponentDefStorage.js")]
        [Import("aura-impl/src/main/resources/aura/AuraComponentService.js")]
    });

    // Mocks necessary to create a new AuraComponentService Object
    var mockOnLoadUtil = Mocks.GetMocks(Object.Global(), {
        "$A": $A,
        "window": function(){},
        "Components": function(){},
        Aura: Aura
    });

    var targetService;
    mockOnLoadUtil(function() {
        targetService = new Aura.Services.AuraComponentService();
    });

    [Fixture]
    function createComponent(){
        var $Amock=Mocks.GetMock(Object.Global(),"$A",{
            assert:function(condition,message){
                if(!condition)throw message;
            },
            enqueueAction:function(){},
            util:{
                isString:function(obj){
                    return typeof obj === 'string';
                },
                isObject:function(obj){
                    return typeof obj === "object" && obj !== null && !this.isArray(obj);
                },
                isFunction:function(obj){
                    return !!obj && Object.prototype.toString.apply(obj) === '[object Function]';
                }
            }

        });

        [Fact]
        function ThrowsIfTypeDoesNotImplementToString(){
            var expected="ComponentService.createComponent(): 'type' must be a valid String.";

            var actual=Record.Exception(function(){
                $Amock(function(){
                    targetService.createComponent(null);
                })
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfAttributesIsNotNullAndNotAnOjbect(){
            var expected="ComponentService.createComponent(): 'attributes' must be a valid Object.";

            var actual=Record.Exception(function(){
                $Amock(function(){
                    targetService.createComponent("test",7357);
                })
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfCallbackisNotAValidFunctionPointer(){
            var expected="ComponentService.createComponent(): 'callback' must be a Function pointer.";

            var actual=Record.Exception(function(){
                $Amock(function(){
                    targetService.createComponent("test",null,{});
                })
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function GetsComponentFromServerWhenNoDef() {
            var actual = false;
            targetService.getComponentConfigs = function(config) {
                return {
                    "definition": null,
                    "descriptor": "blah",
                    "configuration": config
                }
            };
            targetService.requestComponent = function() {
                actual = true;
                return Test.Stubs.Aura.GetAction();
            }

            $Amock(function(){
                targetService.createComponent("test",null,function(){});
            });

            Assert.True(actual);
        }

        [Fact]
        function GetsComponentFromServerWhenDefHasRemoteDependencies() {
            var actual = false;
            var def = {
                    hasRemoteDependencies: function() { return true;}
            };
            targetService.getComponentConfigs = function(config) {
                return {
                    "definition": def,
                    "descriptor": "blah",
                    "configuration": config
                }
            };
            targetService.requestComponent = function() {
                actual = true;
                return Test.Stubs.Aura.GetAction();
            }

            $Amock(function(){
                targetService.createComponent("test",null,function(){});
            });

            Assert.True(actual);
        }
    }

    [Fixture]
    function createComponents(){
        var $Amock=Mocks.GetMock(Object.Global(),"$A",{
            assert:function(condition,message){
                if(!condition)throw message;
            },
            util:{
                isArray:function(obj){
                    return obj instanceof Array;
                },
                isFunction:function(obj){
                    return !!obj && Object.prototype.toString.apply(obj) === '[object Function]';
                }
            }
        });

        [Fact]
        function ThrowsIfCallbackIsNotAValidFunctionPointer(){
            var expected="ComponentService.createComponents(): 'callback' must be a Function pointer.";

            var actual=Record.Exception(function(){
                $Amock(function(){
                    targetService.createComponents([], null);
                })
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfComponentsToCreateIsNotArray() {
            var expected = "ComponentService.createComponents(): 'components' must be a valid Array.";

            var actual = Record.Exception(function() {
                $Amock(function() {
                    targetService.createComponents("ui:button",function(){});
                });
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function CallsCreateComponentApiOncePerComponent() {
            var actual = 0;
            var expected = 3;
            targetService.createComponent = function() {
                actual++;
            }

            $Amock(function() {
                targetService.createComponents([["test1"],["test2"],["test3"]],function(){});
            });

            Assert.Equal(expected, actual);
        }

        [Fact]
        function PassesERRORWhenIncompleteActionFollowsError() {
            var actual;
            var expected = "ERROR";
            targetService.createComponent = function(type, attributes, callback) {
                if (type === "last") {
                    callback(null, "INCOMPLETE");
                } else {
                    callback(null, "ERROR");
                }
            }
            var callback = function(created, overallStatus, statusList) {
                actual = overallStatus;
            };

            $Amock(function() {
                targetService.createComponents([["test1"],["test2"],["last"]], callback);
            });

            Assert.Equal(expected, actual);
        }
    }

    [Fixture]
    function newComponentAsync(){
        [Fact]
        function AssertsConfigIsPresent(){
            // Arrange
            var expected = "ComponentService.newComponentAsync(): 'config' must be a valid Object.";
            var target;
            var actual;
            mockOnLoadUtil(function(){
                target = new Aura.Services.AuraComponentService();
            });

            // Act
            mockOnLoadUtil(function(){
                actual = Record.Exception(function(){
                    target.newComponentAsync(null, function(){}, undefined);
                });
            });

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        function AssertsCallbackIsPresent(){
            // Arrange
            var expected = "ComponentService.newComponentAsync(): 'callback' must be a Function pointer.";
            var target;
            var actual;
            mockOnLoadUtil(function(){
                target = new Aura.Services.AuraComponentService();
            });

            // Act
            mockOnLoadUtil(function(){
                actual = Record.Exception(function(){
                    target.newComponentAsync(null, undefined, {});
                });
            });

            // Assert
            Assert.Equal(expected, actual);
        }
    }

    [Fixture]
    function newComponent() {

        var $Amock=Mocks.GetMock(Object.Global(),"$A",{
            assert:function(condition,message){
                if(!condition)throw message;
            },
            util:{
                isString:function(obj){
                    return typeof obj === 'string';
                },
                isArray:function(obj){
                    return false;
                }
            },
            clientService:{
                allowAccess:function(){return true;}
            }
        });

        // [Fact]
        // function ThrowsComponentClassNotFound(){
        //     var component = "markup://bla:notExist";
        //     var expected = "Component class not found: " + component;
        //     var targetService;
        //     mockOnLoadUtil(function(){
        //         targetService = new Aura.Services.AuraComponentService();
        //     });
        //     targetService.getDef = function(){
        //         return null;
        //     }

        //     // Act
        //     var actual = Record.Exception(function() {
        //         $Amock(function() {
        //             targetService.newComponent({
        //                     componentDef:component,
        //                     "skipCreationPath": true
        //                 },
        //                 null, true, true);
        //         });
        //     });

        //     // Assert
        //     Assert.Equal(expected, actual);
        // }
    }

    [Fixture]
    function hasDefinition() {

        var $Amock=Mocks.GetMock(Object.Global(),"$A",{
            assert:function(condition,message){
                if(!condition)throw message;
            },
            clientService: {
                allowAccess: function () {
                    return true;
                }
            }
        });

        [Fact]
        function NoDescriptorTypeInDefinitionAssumesMarkup() {
            var descriptor = "prefix:name";
            var definition = Test.Stubs.Aura.GetComponentDef(descriptor)
            var actual;

            $Amock(function() {
                targetService.componentDefRegistry["markup://" + descriptor] = definition;
                actual = targetService.hasDefinition(descriptor);
            });

            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfDefinitionIsPresentOnClient() {
            var descriptor = "markup://prefix:name";
            var definition = Test.Stubs.Aura.GetComponentDef(descriptor)
            var actual;

            $Amock(function() {
                targetService.componentDefRegistry[descriptor] = definition;
                actual = targetService.hasDefinition(descriptor);
            });

            Assert.True(actual);

        }

        [Fact]
        function ReturnsFalseIfDefinitionIsNotPresentOnClient() {
            var descriptor = "markup://prefix:name";
            var actual;

            $Amock(function() {
                targetService.componentDefRegistry[descriptor] = null;
                actual = targetService.hasDefinition(descriptor);
            });

            Assert.False(actual);
        }
    }

}


text:
/******************************************************************************
 *
 *  This file contains the implementation of the SMP interface used by
 *  applications that can run over an SMP.
 *
 ******************************************************************************/
#include <string.h>

#include "common/bt_target.h"
//#include "bt_utils.h"
#if SMP_INCLUDED == TRUE
#include "smp_int.h"
#include "stack/smp_api.h"
#include "stack/l2cdefs.h"
#include "l2c_int.h"
#include "btm_int.h"
#include "stack/hcimsgs.h"

#include "stack/btu.h"
#include "p_256_ecc_pp.h"
#include "osi/allocator.h"

/*******************************************************************************
**
** Function         SMP_Init
**
** Description      This function initializes the SMP unit.
**
** Returns          void
**
*******************************************************************************/
void SMP_Init(void)
{
#if SMP_DYNAMIC_MEMORY
    smp_cb_ptr = (tSMP_CB *)osi_malloc(sizeof(tSMP_CB));
#endif
    memset(&smp_cb, 0, sizeof(tSMP_CB));

#if defined(SMP_INITIAL_TRACE_LEVEL)
    smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
#else
    smp_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
#endif
    SMP_TRACE_EVENT ("%s", __FUNCTION__);

    smp_l2cap_if_init();
    /* initialization of P-256 parameters */
    p_256_init_curve(KEY_LENGTH_DWORDS_P256);
}

void SMP_Free(void)
{
    memset(&smp_cb, 0, sizeof(tSMP_CB));
#if SMP_DYNAMIC_MEMORY
    FREE_AND_RESET(smp_cb_ptr);
#endif /* #if SMP_DYNAMIC_MEMORY */
}

/*******************************************************************************
**
** Function         SMP_SetTraceLevel
**
** Description      This function sets the trace level for SMP.  If called with
**                  a value of 0xFF, it simply returns the current trace level.
**
**                  Input Parameters:
**                      level:  The level to set the GATT tracing to:
**                      0xff-returns the current setting.
**                      0-turns off tracing.
**                      >= 1-Errors.
**                      >= 2-Warnings.
**                      >= 3-APIs.
**                      >= 4-Events.
**                      >= 5-Debug.
**
** Returns          The new or current trace level
**
*******************************************************************************/
extern UINT8 SMP_SetTraceLevel (UINT8 new_level)
{
    if (new_level != 0xFF) {
        smp_cb.trace_level = new_level;
    }

    return (smp_cb.trace_level);
}

/*******************************************************************************
**
** Function         SMP_Register
**
** Description      This function register for the SMP services callback.
**
** Returns          void
**
*******************************************************************************/
BOOLEAN SMP_Register (tSMP_CALLBACK *p_cback)
{
    SMP_TRACE_EVENT ("SMP_Register state=%d", smp_cb.state);

    if (smp_cb.p_callback != NULL) {
        SMP_TRACE_ERROR ("SMP_Register: duplicate registration, overwrite it");
    }
    smp_cb.p_callback = p_cback;

    return (TRUE);

}

/*******************************************************************************
**
** Function         SMP_Pair
**
** Description      This function call to perform a SMP pairing with peer device.
**                  Device support one SMP pairing at one time.
**
** Parameters       bd_addr - peer device bd address.
**
** Returns          None
**
*******************************************************************************/
tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
{
    tSMP_CB   *p_cb = &smp_cb;
    UINT8     status = SMP_PAIR_INTERNAL_ERR;

    SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x \n",
                     __FUNCTION__, p_cb->state, p_cb->br_state, p_cb->flags);
    if (p_cb->state != SMP_STATE_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD ||
            p_cb->smp_over_br) {
        /* pending security on going, reject this one */
        return SMP_BUSY;
    } else {
        p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;

        memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);

        if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE)) {
            SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.\n", __FUNCTION__);
            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
            return status;
        }

        return SMP_STARTED;
    }
}

/*******************************************************************************
**
** Function         SMP_BR_PairWith
**
** Description      This function is called to start a SMP pairing over BR/EDR.
**                  Device support one SMP pairing at one time.
**
** Parameters       bd_addr - peer device bd address.
**
** Returns          SMP_STARTED if pairing started, otherwise reason for failure.
**
*******************************************************************************/
tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr)
{
    tSMP_CB   *p_cb = &smp_cb;
    UINT8     status = SMP_PAIR_INTERNAL_ERR;

    SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
                     __func__, p_cb->state, p_cb->br_state, p_cb->flags);

    if (p_cb->state != SMP_STATE_IDLE ||
            p_cb->smp_over_br ||
            p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
        /* pending security on going, reject this one */
        return SMP_BUSY;
    }

    p_cb->role = HCI_ROLE_MASTER;
    p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
    p_cb->smp_over_br = TRUE;

    memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);

    if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE)) {
        SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__);
        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
        return status;
    }

    return SMP_STARTED;
}

/*******************************************************************************
**
** Function         SMP_PairCancel
**
** Description      This function call to cancel a SMP pairing with peer device.
**
** Parameters       bd_addr - peer device bd address.
**
** Returns          TRUE - Pairining is cancelled
**
*******************************************************************************/
BOOLEAN SMP_PairCancel (BD_ADDR bd_addr)
{
    tSMP_CB   *p_cb = &smp_cb;
    UINT8     err_code = SMP_PAIR_FAIL_UNKNOWN;
    BOOLEAN   status = FALSE;

    BTM_TRACE_EVENT ("SMP_CancelPair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
    if ( (p_cb->state != SMP_STATE_IDLE)  &&
            (!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) ) {
        p_cb->is_pair_cancel = TRUE;
        SMP_TRACE_DEBUG("Cancel Pairing: set fail reason Unknown");
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &err_code);
        status = TRUE;
    }

    return status;
}
/*******************************************************************************
**
** Function         SMP_SecurityGrant
**
** Description      This function is called to grant security process.
**
** Parameters       bd_addr - peer device bd address.
**                  res     - result of the operation SMP_SUCCESS if success.
**                            Otherwise, SMP_REPEATED_ATTEMPTS is too many attempts.
**
** Returns          None
**
*******************************************************************************/
void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res)
{
    SMP_TRACE_EVENT ("SMP_SecurityGrant ");

    if (smp_cb.smp_over_br) {
        if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP ||
                smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
                memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) {
            return;
        }

        /* clear the SMP_SEC_REQUEST_EVT event after get grant */
        /* avoid generating duplicate pair request */
        smp_cb.cb_evt = 0;
        smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res);
        return;
    }

    if (smp_cb.state != SMP_STATE_WAIT_APP_RSP ||
            smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
            memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) {
        return;
    }
    /* clear the SMP_SEC_REQUEST_EVT event after get grant */
    /* avoid generate duplicate pair request */
    smp_cb.cb_evt = 0;
    smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &res);
}

/*******************************************************************************
**
** Function         SMP_PasskeyReply
**
** Description      This function is called after Security Manager submitted
**                  passkey request to the application.
**
** Parameters:      bd_addr      - Address of the device for which passkey was requested
**                  res          - result of the operation SMP_SUCCESS if success
**                  passkey - numeric value in the range of
**                  BTM_MIN_PASSKEY_VAL(0) - BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
**
*******************************************************************************/
void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
{
    tSMP_CB *p_cb = & smp_cb;
    UINT8   failure = SMP_PASSKEY_ENTRY_FAIL;

    SMP_TRACE_EVENT ("SMP_PasskeyReply: Key: %d  Result:%d",
                     passkey, res);

    /* If timeout already expired or has been canceled, ignore the reply */
    if (p_cb->cb_evt != SMP_PASSKEY_REQ_EVT) {
        SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong State: %d", p_cb->state);
        return;
    }

    if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) {
        SMP_TRACE_ERROR ("SMP_PasskeyReply() - Wrong BD Addr");
        return;
    }

    if (btm_find_dev (bd_addr) == NULL) {
        SMP_TRACE_ERROR ("SMP_PasskeyReply() - no dev CB");
        return;
    }

    if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS) {
        SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail", passkey);
        /* send pairing failure */
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);

    } else if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_ENT) {
        smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &passkey);
    } else {
        smp_convert_string_to_tk(p_cb->tk, passkey);
    }

    return;
}

/*******************************************************************************
**
** Function         SMP_SetStaticPasskey
**
** Description      This function is called to set static passkey
**
**
** Parameters:      add          - set static passkey when add is TRUE
**                                 clear static passkey when add is FALSE
**                  passkey      - static passkey
**
**
*******************************************************************************/
void SMP_SetStaticPasskey (BOOLEAN add, UINT32 passkey)
{
    SMP_TRACE_DEBUG("static passkey %6d", passkey);
    tSMP_CB *p_cb = & smp_cb;
    if(add) {
        p_cb->static_passkey = passkey;
        p_cb->use_static_passkey = true;
    } else {
        p_cb->static_passkey = 0;
        p_cb->use_static_passkey = false;
    }
}

/*******************************************************************************
**
** Function         SMP_ConfirmReply
**
** Description      This function is called after Security Manager submitted
**                  numeric comparison request to the application.
**
** Parameters:      bd_addr      - Address of the device with which numeric
**                                 comparison was requested
**                  res          - comparison result SMP_SUCCESS if success
**
*******************************************************************************/
void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res)
{
    tSMP_CB *p_cb = & smp_cb;
    UINT8   failure = SMP_NUMERIC_COMPAR_FAIL;

    SMP_TRACE_EVENT ("%s: Result:%d", __FUNCTION__, res);

    /* If timeout already expired or has been canceled, ignore the reply */
    if (p_cb->cb_evt != SMP_NC_REQ_EVT) {
        SMP_TRACE_WARNING ("%s() - Wrong State: %d", __FUNCTION__, p_cb->state);
        return;
    }

    if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) {
        SMP_TRACE_ERROR ("%s() - Wrong BD Addr", __FUNCTION__);
        return;
    }

    if (btm_find_dev (bd_addr) == NULL) {
        SMP_TRACE_ERROR ("%s() - no dev CB", __FUNCTION__);
        return;
    }

    if (res != SMP_SUCCESS) {
        SMP_TRACE_WARNING ("%s() - Numeric Comparison fails", __FUNCTION__);
        /* send pairing failure */
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
    } else {
        smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
    }
}

/*******************************************************************************
**
** Function         SMP_OobDataReply
**
** Description      This function is called to provide the OOB data for
**                  SMP in response to SMP_OOB_REQ_EVT
**
** Parameters:      bd_addr     - Address of the peer device
**                  res         - result of the operation SMP_SUCCESS if success
**                  p_data      - simple pairing Randomizer  C.
**
*******************************************************************************/
void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data)
{
    tSMP_CB *p_cb = & smp_cb;
    UINT8   failure = SMP_OOB_FAIL;
    tSMP_KEY        key;

    SMP_TRACE_EVENT ("%s State: %d  res:%d", __FUNCTION__, smp_cb.state, res);

    /* If timeout already expired or has been canceled, ignore the reply */
    if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT) {
        return;
    }

    if (res != SMP_SUCCESS || len == 0 || !p_data) {
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
    } else {
        if (len > BT_OCTET16_LEN) {
            len = BT_OCTET16_LEN;
        }

        memcpy(p_cb->tk, p_data, len);

        key.key_type    = SMP_KEY_TYPE_TK;
        key.p_data      = p_cb->tk;

        smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &key);
    }
}

/*******************************************************************************
**
** Function         SMP_SecureConnectionOobDataReply
**
** Description      This function is called to provide the SC OOB data for
**                  SMP in response to SMP_SC_OOB_REQ_EVT
**
** Parameters:      p_data      - pointer to the data
**
*******************************************************************************/
void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
{
    tSMP_CB  *p_cb = &smp_cb;

    UINT8  failure = SMP_OOB_FAIL;
    tSMP_SC_OOB_DATA  *p_oob = (tSMP_SC_OOB_DATA *) p_data;
    if (!p_oob) {
        SMP_TRACE_ERROR("%s received no data", __FUNCTION__);
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
        return;
    }

    SMP_TRACE_EVENT ("%s req_oob_type: %d, loc_oob_data.present: %d, "
                     "peer_oob_data.present: %d",
                     __FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
                     p_oob->peer_oob_data.present);

    if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT) {
        return;
    }

    BOOLEAN  data_missing = FALSE;
    switch (p_cb->req_oob_type) {
    case SMP_OOB_PEER:
        if (!p_oob->peer_oob_data.present) {
            data_missing = TRUE;
        }
        break;
    case SMP_OOB_LOCAL:
        if (!p_oob->loc_oob_data.present) {
            data_missing = TRUE;
        }
        break;
    case SMP_OOB_BOTH:
        if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present) {
            data_missing = TRUE;
        }
        break;
    default:
        SMP_TRACE_EVENT ("Unexpected OOB data type requested. Fail OOB");
        data_missing = TRUE;
        break;
    }

    if (data_missing) {
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
        return;
    }

    p_cb->sc_oob_data = *p_oob;

    smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, p_data);
}

/*******************************************************************************
**
** Function         SMP_Encrypt
**
** Description      This function is called to encrypt the data with the specified
**                  key
**
** Parameters:      key                 - Pointer to key key[0] conatins the MSB
**                  key_len             - key length
**                  plain_text          - Pointer to data to be encrypted
**                                        plain_text[0] conatins the MSB
**                  pt_len              - plain text length
**                  p_out                - output of the encrypted texts
**
**  Returns         Boolean - request is successful
*******************************************************************************/
BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len,
                     UINT8 *plain_text, UINT8 pt_len,
                     tSMP_ENC *p_out)

{
    BOOLEAN status = FALSE;
    status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out);
    return status;
}

/*******************************************************************************
**
** Function         SMP_KeypressNotification
**
** Description      This function is called to notify Security Manager about Keypress Notification.
**
** Parameters:     bd_addr      Address of the device to send keypress notification to
**                 value        Keypress notification parameter value
**
*******************************************************************************/
void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value)
{
    tSMP_CB   *p_cb = &smp_cb;

    SMP_TRACE_EVENT ("%s: Value: %d", __FUNCTION__, value);

    if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) {
        SMP_TRACE_ERROR ("%s() - Wrong BD Addr", __FUNCTION__);
        return;
    }

    if (btm_find_dev (bd_addr) == NULL) {
        SMP_TRACE_ERROR ("%s() - no dev CB", __FUNCTION__);
        return;
    }

    /* Keypress Notification is used by a device with KeyboardOnly IO capabilities */
    /* during the passkey entry protocol */
    if (p_cb->local_io_capability != SMP_IO_CAP_IN) {
        SMP_TRACE_ERROR ("%s() - wrong local IO capabilities %d",
                         __FUNCTION__, p_cb->local_io_capability);
        return;
    }

    if (p_cb->selected_association_model != SMP_MODEL_SEC_CONN_PASSKEY_ENT) {
        SMP_TRACE_ERROR ("%s() - wrong protocol %d", __FUNCTION__,
                         p_cb->selected_association_model);
        return;
    }

    smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &value);
}

/*******************************************************************************
**
** Function         SMP_CreateLocalSecureConnectionsOobData
**
** Description      This function is called to start creation of local SC OOB
**                  data set (tSMP_LOC_OOB_DATA).
**
** Parameters:      bd_addr      - Address of the device to send OOB data block to
**
**  Returns         Boolean - TRUE: creation of local SC OOB data set started.
*******************************************************************************/
BOOLEAN SMP_CreateLocalSecureConnectionsOobData (tBLE_BD_ADDR *addr_to_send_to)
{
    tSMP_CB *p_cb = &smp_cb;
#if (!CONFIG_BT_STACK_NO_LOG)
    UINT8   *bd_addr;
#endif

    if (addr_to_send_to == NULL) {
        SMP_TRACE_ERROR ("%s addr_to_send_to is not provided", __FUNCTION__);
        return FALSE;
    }

#if (!CONFIG_BT_STACK_NO_LOG)
    bd_addr = addr_to_send_to->bda;
#endif

    SMP_TRACE_EVENT ("%s addr type: %u,  BDA: %08x%04x,  state: %u, br_state: %u",
                     __FUNCTION__, addr_to_send_to->type,
                     (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
                     (bd_addr[4] << 8) + bd_addr[5],
                     p_cb->state,
                     p_cb->br_state);

    if ((p_cb->state != SMP_STATE_IDLE) || (p_cb->smp_over_br)) {
        SMP_TRACE_WARNING ("%s creation of local OOB data set "\
                           "starts only in IDLE state", __FUNCTION__);
        return FALSE;
    }

    p_cb->sc_oob_data.loc_oob_data.addr_sent_to = *addr_to_send_to;
    smp_sm_event(p_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, NULL);

    return TRUE;
}

#endif /* SMP_INCLUDED */


text:
import * as firebase from 'firebase';

import * as c from '../constants/statusTypes';

export function login(username, pwd) {
  return (dispatch) => {
    dispatch(startLoading());

    firebase.auth()
      .signInWithEmailAndPassword(username, pwd)
      .then((u) => firebase.database().ref(`users/${u.uid}`))
      .then((dbRef) => dbRef.once('value'))
      .then((res) => res.val())
      .then((data) => {
        if(!data || data === {}) return dispatch(errorFetching());

        dispatch(endLoading());
        dispatch(loginFinished(data));
      })
      .catch(e => dispatch(errorFetching(e)));

  }
}

const loginFinished = (data) => {
  return {
    type: c.LOGIN_FINISHED,
    payload: {
      isLogged: true,
      role: data.role,
      username: data.username
    }
  };
};

export function startLoading(){
  console.log('start loading');
  return {
    type: c.START_LOADING
  };
}

export function endLoading(){
  console.log('end loading');
  return {
    type: c.END_LOADING
  };
}

export function errorFetching(e){
  return {
    type: c.ERROR_FETCHING,
    payload: e
  };
}

export function resetError(){
  return {
    type: c.ERROR_RESET
  };
}

export function signUp(data){

  return (dispatch) => {
    dispatch(startLoading());
    firebase
      .auth()
      .createUserWithEmailAndPassword(data.email, data.pwd)
      .then((user) => firebase.database().ref(`/users/${user.uid}`))
      .then((dbRef) => dbRef.set({role: 'regular', username: data.username}))
      .then(() => dispatch(userCreated('regular')))
      .then(() => dispatch(endLoading()))
      .catch((e) => dispatch(errorFetching(e)));
  }
}

export function userCreated(role){
  return {
    type: c.USER_CREATED,
    payload: role
  }
}

export function logout(){
  return {
    type: c.USER_LOGOUT
  }
}


text:
var fs = require('fs');
var filename = '/users/petersirka/desktop/test/dass';
var nosql = require('../index');
var db = nosql.load(filename);
var assert = require('assert');

var write = true;
var read = true;
var remove = true;

var indexComplete = 0;
var indexInsert = 0;

db.on('insert', function(count) {
	console.log('insert ---> ', count);
});

db.on('error', function(err, name) {
	console.log('error ---> ', err, name);
});

db.on('drop', function(a) {
	console.log('DROP', a);
});

db.on('update/remove', function(beg, countUpdate, countDelete) {
	console.log('update/remove ---> ', beg, countUpdate, countDelete);
});

db.on('update', function(doc) {
	console.log('THIS UPDATED', doc);
});

db.on('resume', function() {
	console.log('RESUME');
});

db.on('each', function(status) {
	console.log('each ---> ', status);
});

db.on('complete', function(status) {
	console.log('complete --> ', status);
});

db.on('change', function(description) {
	console.log('change --> ', description);
});

if (fs.existsSync(filename + '.nosql'))
	fs.unlinkSync(filename + '.nosql');

for (var i = 0; i < 100000; i++)
	db.insert({ index: i });

db.insert({ index: 100001 }, 'super');

setTimeout(function() {
	db.remove(function(item) {
		return true;
	}, function(count) {
		console.log('REMOVED:', count);
	}, 'remove doc.index > 105');
}, 4000);