use of io.questdb.std.str.StringSink in project questdb by questdb.
the class CompactMapTest method testUnableToFindFreeSlot.
@Test
public void testUnableToFindFreeSlot() {
// test what happens when map runs out of free slots while trying to
// reshuffle "foreign" entries out of the way
Rnd rnd = new Rnd();
// these have to be power of two for on the limit testing
// QMap will round capacity to next highest power of two!
int N = 256;
int M = 32;
// string is always a number and this number will be hash code of string.
class MockHash implements CompactMap.HashFunction {
@Override
public long hash(MemoryR mem, long offset, long size) {
// we have single key field, which is string
// the offset of string is 8 bytes for key cell + 4 bytes for string length, total is 12
char c = mem.getChar(offset + 12);
return c - '0';
}
}
StringSink sink = new StringSink();
// tweak capacity in such a way that we only have one spare slot before resize is needed
// this way algo that shuffles "foreign" slots away should face problems
double loadFactor = 0.9999999;
try (CompactMap map = new CompactMap(1024 * 1024, new SingleColumnType(ColumnType.STRING), new SingleColumnType(ColumnType.LONG), (long) (N * loadFactor), loadFactor, new MockHash(), 1, Integer.MAX_VALUE)) {
// assert that key capacity is what we expect, otherwise this test would be useless
Assert.assertEquals(N, map.getActualCapacity());
testUnableToFindFreeSlot0(rnd, N, M, sink, map);
map.clear();
rnd.reset();
testUnableToFindFreeSlot0(rnd, N, M, sink, map);
}
}
use of io.questdb.std.str.StringSink in project questdb by questdb.
the class CompactMapTest method testUnableToFindFreeSlot2.
@Test
public void testUnableToFindFreeSlot2() {
// test that code that deals with key collection is always
// protected by map capacity check.
Rnd rnd = new Rnd();
// these have to be power of two for on the limit testing
// QMap will round capacity to next highest power of two!
int N = 256;
int M = 32;
StringSink sink = new StringSink();
// tweak capacity in such a way that we only have one spare slot before resize is needed
// this way algo that shuffles "foreign" slots away should face problems
double loadFactor = 0.9999999;
try (CompactMap map = new CompactMap(1024 * 1024, new SingleColumnType(ColumnType.STRING), new SingleColumnType(ColumnType.LONG), (long) (N * loadFactor), loadFactor, new MockHash(), 1, Integer.MAX_VALUE)) {
// assert that key capacity is what we expect, otherwise this test would be useless
Assert.assertEquals(N, map.getActualCapacity());
long target = map.getKeyCapacity();
sink.clear();
sink.put("000");
for (long i = 0; i < target - 2; i++) {
// keep the first character
sink.clear(3);
rnd.nextChars(sink, 5);
MapKey key = map.withKey();
key.putStr(sink);
MapValue value = key.createValue();
Assert.assertTrue(value.isNew());
value.putLong(0, i + 1);
}
sink.clear();
sink.put(target - 2);
populate(rnd, sink, map, target - 1, M + N, 3);
// assert result
rnd.reset();
sink.clear();
sink.put("000");
assertMap(rnd, sink, map, 0, target - 2, 3);
sink.clear();
sink.put(target - 2);
assertMap(rnd, sink, map, target - 1, M + N, 3);
}
}
use of io.questdb.std.str.StringSink in project questdb by questdb.
the class ContinuousMemoryMTest method testLong256Append3.
@Test
public void testLong256Append3() throws Exception {
withMem((rwMem, roMem) -> {
final int N = 1_000_000;
StringSink sink = new StringSink();
for (int i = 0; i < N; i++) {
Numbers.appendLong256(rnd.nextLong(), rnd.nextLong(), rnd.nextLong(), rnd.nextLong(), sink);
rwMem.putLong256(sink);
sink.clear();
}
roMem.extend(rwMem.size());
// read these values back from
assertLong256(rwMem, N);
assertLong256(roMem, N);
});
}
use of io.questdb.std.str.StringSink in project questdb by questdb.
the class AlterTableLineTcpReceiverTest method testRandomColumnAddedDeleted.
@Test
public void testRandomColumnAddedDeleted() throws Exception {
runInContext((server) -> {
LinkedList<Integer> columnsAdded = new LinkedList<>();
Rnd rnd = new Rnd();
StringSink symbols = new StringSink();
StringSink fields = new StringSink();
for (int i = 1; i < 30; i++) {
if (columnsAdded.size() == 0 || rnd.nextPositiveInt() % 3 != 1) {
// add column
boolean isSymbol = rnd.nextBoolean();
symbols.clear();
for (int col : columnsAdded) {
if (col > 0) {
symbols.put(",column_").put(col).put("=").put(col);
}
}
fields.clear();
int added = 0;
for (int col : columnsAdded) {
if (col < 0) {
col = Math.abs(col);
if (!isSymbol || added++ > 0) {
fields.put(',');
}
fields.put("column_").put(col).put("=\"").put(col).put('\"');
}
}
String lineData = isSymbol ? String.format("plug,column_%d=%d,iteration=%d%s %s %d\n", i, i, i % 5, symbols, fields, i * Timestamps.MINUTE_MICROS * 20 * 1000) : String.format("plug,iteration=%d%s column_%d=\"%d\"%s %d\n", i % 5, symbols, i, i, fields, i * Timestamps.MINUTE_MICROS * 20 * 1000);
send(server, lineData);
columnsAdded.add(isSymbol ? i : -i);
} else {
try (TableWriter tableWriter = engine.getWriter(AllowAllCairoSecurityContext.INSTANCE, "plug", "ilp test")) {
int dropCol = columnsAdded.get(rnd.nextPositiveInt() % columnsAdded.size());
tableWriter.removeColumn("column_" + Math.abs(dropCol));
columnsAdded.remove((Object) dropCol);
}
}
}
String expected = "iteration\ttimestamp\tcolumn_24\tcolumn_25\tcolumn_26\n" + "1\t1970-01-01T00:20:00.000000Z\t\t\t\n" + "2\t1970-01-01T00:40:00.000000Z\t\t\t\n" + "3\t1970-01-01T01:00:00.000000Z\t\t\t\n" + "4\t1970-01-01T01:20:00.000000Z\t\t\t\n" + "2\t1970-01-01T02:20:00.000000Z\t\t\t\n" + "4\t1970-01-01T03:00:00.000000Z\t\t\t\n" + "2\t1970-01-01T04:00:00.000000Z\t\t\t\n" + "3\t1970-01-01T04:20:00.000000Z\t\t\t\n" + "1\t1970-01-01T05:20:00.000000Z\t\t\t\n" + "3\t1970-01-01T06:00:00.000000Z\t\t\t\n" + "0\t1970-01-01T06:40:00.000000Z\t\t\t\n" + "2\t1970-01-01T07:20:00.000000Z\t\t\t\n" + "4\t1970-01-01T08:00:00.000000Z\t24\t\t\n" + "0\t1970-01-01T08:20:00.000000Z\t24\t25\t\n" + "1\t1970-01-01T08:40:00.000000Z\t24\t25\t26\n" + "2\t1970-01-01T09:00:00.000000Z\t24\t25\t26\n";
assertTable(expected);
});
}
use of io.questdb.std.str.StringSink in project questdb by questdb.
the class SqlOptimiser method doReplaceLiteral0.
private ExpressionNode doReplaceLiteral0(ExpressionNode node, QueryModel translatingModel, @Nullable QueryModel innerModel, QueryModel validatingModel) throws SqlException {
final LowerCaseCharSequenceObjHashMap<CharSequence> map = translatingModel.getColumnNameToAliasMap();
int index = map.keyIndex(node.token);
if (index > -1) {
// there is a possibility that column references join table, but in a different way
// for example. main column could be tab1.y and the "missing" one just "y"
// which is the same thing.
// To disambiguate this situation we need to go over all join tables and see if the
// column matches any of join tables unambiguously.
final int joinCount = validatingModel.getJoinModels().size();
if (joinCount > 1) {
boolean found = false;
final StringSink sink = Misc.getThreadLocalBuilder();
sink.clear();
for (int i = 0; i < joinCount; i++) {
final QueryModel jm = validatingModel.getJoinModels().getQuick(i);
if (jm.getAliasToColumnMap().keyIndex(node.token) < 0) {
if (found) {
throw SqlException.ambiguousColumn(node.position);
}
if (jm.getAlias() != null) {
sink.put(jm.getAlias().token);
} else {
sink.put(jm.getTableName().token);
}
sink.put('.');
sink.put(node.token);
if ((index = map.keyIndex(sink)) < 0) {
found = true;
}
}
}
if (found) {
return nextLiteral(map.valueAtQuick(index), node.position);
}
}
// this is the first time we see this column and must create alias
CharSequence alias = createColumnAlias(node, translatingModel);
QueryColumn column = queryColumnPool.next().of(alias, node);
// add column to both models
addColumnToTranslatingModel(column, translatingModel, validatingModel);
if (innerModel != null) {
innerModel.addBottomUpColumn(column);
}
return nextLiteral(alias, node.position);
}
return nextLiteral(map.valueAtQuick(index), node.position);
}
Aggregations