public String convertFunnel(String project, String connectorField, int idx, FunnelStep funnelStep, Optional<String> dimension, Optional<String> segment, LocalDate startDate, LocalDate endDate) { String table = checkProject(project, '"') + "." + ValidationUtil.checkCollection(funnelStep.getCollection()); Optional<String> filterExp = funnelStep.getExpression().map(value -> RakamSqlFormatter.formatExpression(value, name -> name.getParts().stream().map(e -> formatIdentifier(e, '"')).collect(Collectors.joining(".")), name -> formatIdentifier("step" + idx, '"') + "." + name, '"')); String format = format("SELECT %s %s %s, %d as step, %s from %s %s %s", segment.isPresent() ? "" : dimension.map(ValidationUtil::checkTableColumn).map(v -> v + ",").orElse(""), segment.isPresent() ? format(timeStampMapping.get(FunnelTimestampSegments.valueOf(segment.get().replace(" ", "_").toUpperCase())), dimension.get()) + " as " + checkTableColumn(dimension.get() + "_segment") + "," : "", format(connectorField, "step" + idx), idx + 1, checkTableColumn(projectConfig.getTimeColumn()), table, "step" + idx, filterExp.map(v -> "where " + v).orElse("")); return format; } }
@GET @Path("/segments") public Map<FieldType, List<FunnelSegment>> segments() { return ImmutableMap.of(FieldType.TIMESTAMP, Arrays.stream(FunnelQueryExecutor.FunnelTimestampSegments.values()).map(e -> new FunnelSegment(e.name(), e.getDisplayName())).collect(Collectors.toList())); }
if (!timeStampMapping.containsKey(FunnelTimestampSegments.valueOf(segment.get().toUpperCase()))) { throw new RakamException("When dimension is of type TIMESTAMP, segmenting should be done on TIMESTAMP field.", BAD_REQUEST); mainSelect.add(format("select %s %s %d as step, %s %s from %s where %s between timestamp '%s' and timestamp '%s' and %s", dimension.map(v -> checkTableColumn(v) + ", ").orElse(""), segment.isPresent() ? format(timeStampMapping.get(FunnelTimestampSegments.valueOf(segment.get().replace(" ", "_").toUpperCase())), dimension.get()) + " as " + checkTableColumn(dimension.get() + "_segment") + "," : "", i,
String val = dimension.get(); if (val.equals(projectConfig.getTimeColumn())) { if (!segment.isPresent() || !timeStampMapping.containsKey(FunnelTimestampSegments.valueOf(segment.get().toUpperCase()))) { throw new RakamException("When dimension is time, segmenting should be done on timestamp field.", BAD_REQUEST); if (!segment.isPresent() || !timeStampMapping.containsKey(FunnelTimestampSegments.valueOf(segment.get().toUpperCase()))) { throw new RakamException("When dimension is of type TIMESTAMP, segmenting should be done on timestamp field.", BAD_REQUEST);
if (!segment.isPresent() || !timeStampMapping.containsKey(FunnelTimestampSegments.valueOf(segment.get().toUpperCase()))) { throw new RakamException("When dimension is time, segmenting should be done on timestamp field.", BAD_REQUEST); .filter(c -> !c.getValue().contains(dimension.get())).findAny().get().getValue().stream() .filter(d -> d.getName().equals(dimension.get())).findAny().get().getType().getPrettyName().equals("TIMESTAMP")) { if (!segment.isPresent() || !timeStampMapping.containsKey(FunnelTimestampSegments.valueOf(segment.get().toUpperCase()))) { throw new RakamException("When dimension is of type TIMESTAMP, segmenting should be done on timestamp field.", BAD_REQUEST);
private String applySegment(String v, Optional<String> segment) { return String.format(timeStampMapping.get(FunnelTimestampSegments.valueOf(segment.get().replace(" ", "_").toUpperCase())), v); } }
@JsonProperty public String value() { return name(); }
private String applySegment(String v, Optional<String> segment) { return String.format(timeStampMapping.get(FunnelTimestampSegments.valueOf(segment.get().replace(" ", "_").toUpperCase())), v); } }
@JsonCreator FunnelTimestampSegments get(String name) { return valueOf(name.toUpperCase()); }
@Test public void testSegmentApproximate() throws Exception { QueryResult query = getFunnelQueryExecutor().query(new RequestContext(PROJECT_NAME, null), of(new FunnelStep("test0", Optional.of("teststr = 'test1'")), new FunnelStep("test1", Optional.of("teststr = 'test1'"))), Optional.of("_time"), Optional.of(FunnelQueryExecutor.FunnelTimestampSegments.DAY_OF_MONTH.value()), LocalDate.ofEpochDay(0), LocalDate.ofEpochDay(SCALE_FACTOR), Optional.empty(), UTC, Optional.empty(), APPROXIMATE).getResult().join(); assertFalse(query.isFailed()); assertEquals(query.getResult(), of(of("Step 1", "1th day", 3L), of("Step 2", "1th day", 3L))); }
@Test public void testSegmentOrdered() throws Exception { QueryResult query = getFunnelQueryExecutor().query(new RequestContext(PROJECT_NAME, null), of(new FunnelStep("test0", Optional.of("teststr = 'test1'")), new FunnelStep("test1", Optional.of("teststr = 'test1'"))), Optional.of("_time"), Optional.of(FunnelQueryExecutor.FunnelTimestampSegments.DAY_OF_MONTH.value()), LocalDate.ofEpochDay(0), LocalDate.ofEpochDay(SCALE_FACTOR), Optional.empty(), UTC, Optional.empty(), ORDERED).getResult().join(); assertFalse(query.isFailed()); assertEquals(query.getResult(), of(of("Step 1", "1th day", 3L), of("Step 2", "1th day", 3L))); }
@Test public void testSegment() throws Exception { QueryResult query = getFunnelQueryExecutor().query(new RequestContext(PROJECT_NAME, null), of(new FunnelStep("test0", Optional.of("teststr = 'test1'")), new FunnelStep("test1", Optional.of("teststr = 'test1'"))), Optional.of("_time"), Optional.of(FunnelQueryExecutor.FunnelTimestampSegments.DAY_OF_MONTH.value()), LocalDate.ofEpochDay(0), LocalDate.ofEpochDay(SCALE_FACTOR), Optional.empty(), UTC, Optional.empty(), NORMAL).getResult().join(); assertFalse(query.isFailed()); assertEquals(query.getResult(), of(of("Step 1", "1th day", 3L), of("Step 2", "1th day", 3L))); }