blob: f2065e981febfff71ba918b0fad949d8be3a2eaf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { ExternalLink, Field } from '../components';
import { deepGet, EMPTY_ARRAY, EMPTY_OBJECT } from '../utils';
import { IngestionSpec } from './ingestion-spec';
import {
BASIC_TIME_FORMATS,
DATETIME_TIME_FORMATS,
DATE_ONLY_TIME_FORMATS,
OTHER_TIME_FORMATS,
} from './time';
import { Transform } from './transform-spec';
const NO_SUCH_COLUMN = '!!!_no_such_column_!!!';
export const TIME_COLUMN = '__time';
export const PLACEHOLDER_TIMESTAMP_SPEC: TimestampSpec = {
column: NO_SUCH_COLUMN,
missingValue: '1970-01-01T00:00:00Z',
};
export const REINDEX_TIMESTAMP_SPEC: TimestampSpec = {
column: TIME_COLUMN,
format: 'millis',
};
export const CONSTANT_TIMESTAMP_SPEC: TimestampSpec = {
column: NO_SUCH_COLUMN,
missingValue: '2010-01-01T00:00:00Z',
};
export type TimestampSchema = 'none' | 'column' | 'expression';
export function getTimestampSchema(spec: IngestionSpec): TimestampSchema {
const transforms: Transform[] =
deepGet(spec, 'spec.dataSchema.transformSpec.transforms') || EMPTY_ARRAY;
const timeTransform = transforms.find(transform => transform.name === TIME_COLUMN);
if (timeTransform) return 'expression';
const timestampSpec = deepGet(spec, 'spec.dataSchema.timestampSpec') || EMPTY_OBJECT;
return timestampSpec.column === NO_SUCH_COLUMN ? 'none' : 'column';
}
export interface TimestampSpec {
column?: string;
format?: string;
missingValue?: string;
}
export function getTimestampSpecColumnFromSpec(spec: IngestionSpec): string {
// For the default https://github.com/apache/druid/blob/master/core/src/main/java/org/apache/druid/data/input/impl/TimestampSpec.java#L44
return deepGet(spec, 'spec.dataSchema.timestampSpec.column') || 'timestamp';
}
export function getTimestampSpecConstantFromSpec(spec: IngestionSpec): string | undefined {
return deepGet(spec, 'spec.dataSchema.timestampSpec.missingValue');
}
export function getTimestampSpecExpressionFromSpec(spec: IngestionSpec): string | undefined {
const transforms: Transform[] =
deepGet(spec, 'spec.dataSchema.transformSpec.transforms') || EMPTY_ARRAY;
const timeTransform = transforms.find(transform => transform.name === TIME_COLUMN);
if (!timeTransform) return;
return timeTransform.expression;
}
export function getTimestampDetailFromSpec(spec: IngestionSpec): string {
const timestampSchema = getTimestampSchema(spec);
switch (timestampSchema) {
case 'none':
return `Constant: ${getTimestampSpecConstantFromSpec(spec)}`;
case 'column':
return `Column: ${getTimestampSpecColumnFromSpec(spec)}`;
case 'expression':
return `Expression: ${getTimestampSpecExpressionFromSpec(spec)}`;
}
return '-';
}
export const TIMESTAMP_SPEC_FIELDS: Field<TimestampSpec>[] = [
{
name: 'column',
type: 'string',
defaultValue: 'timestamp',
required: true,
},
{
name: 'format',
type: 'string',
defaultValue: 'auto',
suggestions: [
...BASIC_TIME_FORMATS,
{
group: 'Date and time formats',
suggestions: DATETIME_TIME_FORMATS,
},
{
group: 'Date only formats',
suggestions: DATE_ONLY_TIME_FORMATS,
},
{
group: 'Other time formats',
suggestions: OTHER_TIME_FORMATS,
},
],
info: (
<p>
Specify your timestamp format by using the suggestions menu or typing in a{' '}
<ExternalLink href="https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html">
format string
</ExternalLink>
.
</p>
),
},
{
name: 'missingValue',
type: 'string',
placeholder: '(optional)',
info: (
<p>Specify a static value for cases when the source time column is missing or is null.</p>
),
suggestions: ['2020-01-01T00:00:00Z'],
},
];
export const CONSTANT_TIMESTAMP_SPEC_FIELDS: Field<TimestampSpec>[] = [
{
name: 'missingValue',
label: 'Placeholder value',
type: 'string',
info: <p>The placeholder value that will be used as the timestamp.</p>,
},
];
export function issueWithTimestampSpec(
timestampSpec: TimestampSpec | undefined,
): string | undefined {
if (!timestampSpec) return 'no spec';
if (!timestampSpec.column && !timestampSpec.missingValue) return 'timestamp spec is blank';
return;
}