mirror of
https://github.com/lingble/clickhouse.git
synced 2025-11-09 16:46:01 +00:00
345 lines
9.0 KiB
JavaScript
345 lines
9.0 KiB
JavaScript
const
|
|
stream = require('stream'),
|
|
expect = require('expect.js'),
|
|
_ = require('lodash'),
|
|
{ ClickHouse } = require('../.');
|
|
|
|
|
|
const
|
|
clickhouse = new ClickHouse({debug: false}),
|
|
rowCount = _.random(50 * 1024, 1024 * 1024),
|
|
sql = `SELECT
|
|
number,
|
|
toString(number * 2) AS str,
|
|
toDate(number + 1) AS date
|
|
FROM system.numbers
|
|
LIMIT ${rowCount}`;
|
|
|
|
|
|
describe('Exec', () => {
|
|
it('should return not null object', async () => {
|
|
const sqlList = [
|
|
'DROP TABLE IF EXISTS session_temp',
|
|
|
|
`CREATE TABLE session_temp (
|
|
date Date,
|
|
time DateTime,
|
|
mark String,
|
|
ips Array(UInt32),
|
|
queries Nested (
|
|
act String,
|
|
id UInt32
|
|
)
|
|
)
|
|
ENGINE=MergeTree(date, (mark, time), 8192)`,
|
|
|
|
'OPTIMIZE TABLE session_temp PARTITION 201807 FINAL'
|
|
];
|
|
|
|
for(const query of sqlList) {
|
|
const r = await clickhouse.query(query).toPromise();
|
|
|
|
expect(r).to.be.ok();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('Select', () => {
|
|
it('use callback', callback => {
|
|
clickhouse.query(sql).exec((err, rows) => {
|
|
expect(err).to.not.be.ok();
|
|
|
|
expect(rows).to.have.length(rowCount);
|
|
expect(rows[0]).to.eql({ number: 0, str: '0', date: '1970-01-02' });
|
|
|
|
callback();
|
|
});
|
|
});
|
|
|
|
|
|
it('use callback #2', callback => {
|
|
clickhouse.query(sql, (err, rows) => {
|
|
expect(err).to.not.be.ok();
|
|
|
|
expect(rows).to.have.length(rowCount);
|
|
expect(rows[0]).to.eql({ number: 0, str: '0', date: '1970-01-02' });
|
|
|
|
callback();
|
|
});
|
|
});
|
|
|
|
|
|
it('use stream', function(callback) {
|
|
this.timeout(10000);
|
|
|
|
let i = 0;
|
|
let error = null;
|
|
|
|
clickhouse.query(sql).stream()
|
|
.on('data', () => ++i)
|
|
.on('error', err => error = err)
|
|
.on('end', () => {
|
|
expect(error).to.not.be.ok();
|
|
expect(i).to.be(rowCount);
|
|
|
|
callback();
|
|
});
|
|
});
|
|
|
|
|
|
it('use stream with pause/resume', function(callback) {
|
|
const
|
|
count = 10,
|
|
pause = 1000,
|
|
ts = Date.now();
|
|
|
|
this.timeout(count * pause * 2);
|
|
|
|
let i = 0,
|
|
error = null;
|
|
|
|
const stream = clickhouse.query(`SELECT number FROM system.numbers LIMIT ${count}`).stream();
|
|
|
|
stream
|
|
.on('data', () => {
|
|
++i;
|
|
|
|
stream.pause();
|
|
|
|
setTimeout(() => stream.resume(), pause);
|
|
})
|
|
.on('error', err => error = err)
|
|
.on('end', () => {
|
|
expect(error).to.not.be.ok();
|
|
expect(i).to.be(count);
|
|
expect(Date.now() - ts).to.be.greaterThan(count * pause);
|
|
|
|
callback();
|
|
})
|
|
});
|
|
|
|
|
|
// Waiting for Node.js 10
|
|
// it('use async for', async function() {
|
|
// let i = 0;
|
|
// for await (const row of await clickhouse.query(sql).stream()) {
|
|
// ++i;
|
|
// expect(row).to.have.key('number');
|
|
// expect(row).to.have.key('str');
|
|
// expect(row).to.have.key('date');
|
|
// }
|
|
//
|
|
// expect(i).to.be(rowCount);
|
|
// });
|
|
|
|
it('use promise and await/async', async () => {
|
|
let rows = await clickhouse.query(sql).toPromise();
|
|
|
|
expect(rows).to.have.length(rowCount);
|
|
expect(rows[0]).to.eql({ number: 0, str: '0', date: '1970-01-02' });
|
|
});
|
|
|
|
|
|
it('use select with external', async () => {
|
|
const result = await clickhouse.query('SELECT count(*) AS count FROM temp_table', {
|
|
external: [
|
|
{
|
|
name: 'temp_table',
|
|
data: _.range(0, rowCount).map(i => `str${i}`)
|
|
},
|
|
]
|
|
}).toPromise();
|
|
|
|
expect(result).to.be.ok();
|
|
expect(result).to.have.length(1);
|
|
expect(result[0]).to.have.key('count');
|
|
expect(result[0].count).to.be(rowCount);
|
|
});
|
|
});
|
|
|
|
|
|
describe('session', () => {
|
|
it('use session', async () => {
|
|
const sessionId = clickhouse.sessionId;
|
|
clickhouse.sessionId = Date.now();
|
|
|
|
const result = await clickhouse.query(
|
|
`CREATE TEMPORARY TABLE test_table
|
|
(_id String, str String)
|
|
ENGINE=Memory`
|
|
).toPromise();
|
|
expect(result).to.be.ok();
|
|
|
|
clickhouse.sessionId = Date.now();
|
|
const result2 = await clickhouse.query(
|
|
`CREATE TEMPORARY TABLE test_table
|
|
(_id String, str String)
|
|
ENGINE=Memory`
|
|
).toPromise();
|
|
expect(result2).to.be.ok();
|
|
|
|
clickhouse.sessionId = sessionId;
|
|
});
|
|
});
|
|
|
|
|
|
describe('queries', () => {
|
|
it('insert field as array', async () => {
|
|
clickhouse.sessionId = Date.now();
|
|
await clickhouse.query('CREATE DATABASE IF NOT EXISTS test').toPromise();
|
|
await clickhouse.query('use test').toPromise();
|
|
await clickhouse.query(`
|
|
CREATE TABLE IF NOT EXISTS test_array (
|
|
date Date,
|
|
str String,
|
|
arr Array(String),
|
|
arr2 Array(Date),
|
|
arr3 Array(UInt8)
|
|
) ENGINE=MergeTree(date, date, 8192)
|
|
`).toPromise();
|
|
|
|
const rows = [
|
|
{
|
|
date: '2018-01-01',
|
|
str: 'Вам, проживающим за оргией оргию,',
|
|
arr: [],
|
|
arr2: ['1915-01-02', '1915-01-03'],
|
|
arr3: [1,2,3,4,5]
|
|
},
|
|
|
|
{
|
|
date: '2018-02-01',
|
|
str: 'имеющим ванную и теплый клозет!',
|
|
arr: ['5670000000', 'asdas dasf'],
|
|
arr2: ['1915-02-02'],
|
|
arr3: []
|
|
}
|
|
];
|
|
|
|
|
|
const r = await clickhouse.insert('INSERT INTO test_array (date, arr, arr2, arr3)', rows).toPromise();
|
|
expect(r).to.be.ok();
|
|
|
|
|
|
clickhouse.sessionId = null;
|
|
});
|
|
|
|
|
|
it('queries', async () => {
|
|
const result = await clickhouse.query('DROP TABLE IF EXISTS session_temp').toPromise();
|
|
expect(result).to.be.ok();
|
|
|
|
const result2 = await clickhouse.query('DROP TABLE IF EXISTS session_temp2').toPromise();
|
|
expect(result2).to.be.ok();
|
|
|
|
const result3 = await clickhouse.query('CREATE TABLE session_temp (str String) ENGINE=MergeTree PARTITION BY tuple() ORDER BY tuple()').toPromise();
|
|
expect(result3).to.be.ok();
|
|
|
|
const result4 = await clickhouse.query('CREATE TABLE session_temp2 (str String) ENGINE=MergeTree PARTITION BY tuple() ORDER BY tuple()').toPromise();
|
|
expect(result4).to.be.ok();
|
|
|
|
const data = _.range(0, rowCount).map(r => [r]);
|
|
const result5 = await clickhouse.insert(
|
|
'INSERT INTO session_temp', data
|
|
).toPromise();
|
|
expect(result5).to.be.ok();
|
|
|
|
const rows = await clickhouse.query('SELECT COUNT(*) AS count FROM session_temp').toPromise();
|
|
expect(rows).to.be.ok();
|
|
expect(rows).to.have.length(1);
|
|
expect(rows[0]).to.have.key('count');
|
|
expect(rows[0].count).to.be(data.length);
|
|
expect(rows[0].count).to.be(rowCount);
|
|
|
|
const result6 = await clickhouse.query('TRUNCATE TABLE session_temp').toPromise();
|
|
expect(result6).to.be.ok();
|
|
|
|
const ws = clickhouse.insert('INSERT INTO session_temp').stream();
|
|
let count = 0;
|
|
|
|
for(let i = 1; i <= rowCount; i++) {
|
|
await ws.writeRow(
|
|
[
|
|
_.range(0, 50).map(
|
|
j => `${i}:${i * 2}:${j}`
|
|
).join('-')
|
|
]
|
|
);
|
|
++count;
|
|
}
|
|
const result7 = await ws.exec();
|
|
expect(result7).to.be.ok();
|
|
expect(count).to.be(rowCount);
|
|
|
|
clickhouse.isUseGzip = true;
|
|
const rs = clickhouse.query(sql).stream();
|
|
|
|
const tf = new stream.Transform({
|
|
objectMode : true,
|
|
transform : function (chunk, enc, cb) {
|
|
cb(null, JSON.stringify(chunk) + '\n');
|
|
}
|
|
});
|
|
|
|
clickhouse.sessionId = Date.now();
|
|
const ws2 = clickhouse.insert('INSERT INTO session_temp2').stream();
|
|
|
|
const result8 = await rs.pipe(tf).pipe(ws2).exec();
|
|
expect(result8).to.be.ok();
|
|
clickhouse.isUseGzip = false;
|
|
|
|
const result9 = await clickhouse.query('SELECT count(*) AS count FROM session_temp').toPromise();
|
|
const result10 = await clickhouse.query('SELECT count(*) AS count FROM session_temp2').toPromise();
|
|
expect(result9).to.eql(result10);
|
|
|
|
const result11 = await clickhouse.query('SELECT date FROM test.test_array GROUP BY date WITH TOTALS').withTotals().toPromise();
|
|
expect(result11).to.have.key('meta');
|
|
expect(result11).to.have.key('data');
|
|
expect(result11).to.have.key('totals');
|
|
expect(result11).to.have.key('rows');
|
|
expect(result11).to.have.key('statistics');
|
|
|
|
const result111 = await clickhouse.query('DROP TABLE IF EXISTS test_int_temp').toPromise();
|
|
expect(result111).to.be.ok();
|
|
|
|
const result12 = await clickhouse.query('CREATE TABLE test_int_temp (int_value Int8 ) ENGINE=Memory').toPromise();
|
|
expect(result12).to.be.ok();
|
|
|
|
const int_value_data = [{int_value: 0}]
|
|
const result13 = await clickhouse.insert('INSERT INTO test_int_temp (int_value)', int_value_data).toPromise();
|
|
expect(result13).to.be.ok();
|
|
|
|
const result14 = await clickhouse.query('SELECT int_value FROM test_int_temp').toPromise();
|
|
expect(result14).to.eql(int_value_data);
|
|
});
|
|
});
|
|
|
|
|
|
describe('response codes', () => {
|
|
it('table is not exists', async () => {
|
|
try {
|
|
const result = await clickhouse.query('DROP TABLE session_temp').toPromise();
|
|
expect(result).to.be.ok();
|
|
|
|
await clickhouse.query('SELECT COUNT(*) AS count FROM session_temp').toPromise();
|
|
expect().fail('You should not be here');
|
|
} catch (err) {
|
|
expect(err).to.be.ok();
|
|
expect(err).to.have.key('code');
|
|
expect(err.code).to.be(60);
|
|
}
|
|
|
|
// try {
|
|
// let result = await clickhouse.query('DROP TABLE session_temp2').toPromise();
|
|
// expect(result).to.be.ok();
|
|
|
|
// await clickhouse.query('SELECT COUNT(*) AS count FROM session_temp2').toPromise();
|
|
// expect().fail('You should not be here2');
|
|
// } catch (err) {
|
|
// expect(err).to.be.ok();
|
|
// expect(err).to.have.key('code');
|
|
// expect(err.code).to.be(60);
|
|
// }
|
|
});
|
|
});
|