#include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int ILLEGAL_COLUMN; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; } DateTime64::NativeType nowSubsecond(UInt32 scale) { timespec spec; clock_gettime(CLOCK_REALTIME, &spec); return decimalFromComponents(spec.tv_sec, spec.tv_nsec, scale).value; } class FunctionNow64 : public IFunction { public: static constexpr auto name = "now64"; static FunctionPtr create(const Context &) { return std::make_shared(); } String getName() const override { return name; } bool isVariadic() const override { return true; } size_t getNumberOfArguments() const override { return 0; } ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return ColumnNumbers{0}; } bool isDeterministic() const override { return false; } // Return type depends on argument value. DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override { UInt32 scale = DataTypeDateTime64::default_scale; // Type check is similar to the validateArgumentType, trying to keep error codes and messages as close to the said function as possible. if (arguments.size() >= 1) { const auto & argument = arguments[0]; if (!isInteger(argument.type) || !isColumnConst(*argument.column)) throw Exception("Illegal type " + argument.type->getName() + " of 0" + " argument of function " + getName() + ". Expected const integer.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); scale = argument.column->get64(0); } return std::make_shared(scale); } void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override { UInt32 scale = DataTypeDateTime64::default_scale; if (arguments.size() == 1) { const IColumn * scale_column = block.getByPosition(arguments[0]).column.get(); if (!isColumnConst(*scale_column)) throw Exception("Unsupported argument type: " + scale_column->getName() + + " for function " + getName() + ". Expected const integer.", ErrorCodes::ILLEGAL_COLUMN); scale = scale_column->get64(0); } block.getByPosition(result).column = DataTypeDateTime64(scale).createColumnConst(input_rows_count, nowSubsecond(scale)); } }; void registerFunctionNow64(FunctionFactory & factory) { factory.registerFunction(FunctionFactory::CaseInsensitive); } }