#pragma once #include #include #include #include #include #include #include #include struct Node; namespace NYql { class TExprNode; struct TExprContext; } namespace NYql::NPg { constexpr ui32 UnknownOid = 705; constexpr ui32 AnyOid = 2276; constexpr ui32 AnyArrayOid = 2277; constexpr ui32 AnyNonArrayOid = 2776; constexpr ui32 AnyElementOid = 2283; constexpr ui32 RecordOid = 2249; constexpr ui32 VarcharOid = 1043; constexpr ui32 TextOid = 25; // copied from pg_class.h enum class ERelPersistence : char { Permanent = 'p', Unlogged = 'u', Temp = 't', }; enum class EOperKind { Binary, LeftUnary, RightUnary }; struct TOperDesc { ui32 OperId = 0; TString Name; TString Descr; EOperKind Kind = EOperKind::Binary; ui32 LeftType = 0; ui32 RightType = 0; ui32 ResultType = 0; ui32 ProcId = 0; ui32 ComId = 0; ui32 NegateId = 0; ui32 ExtensionIndex = 0; }; enum class EProcKind : char { Function = 'f', Aggregate = 'a', Window = 'w' }; constexpr ui32 LangInternal = 12; constexpr ui32 LangC = 13; constexpr ui32 LangSQL = 14; struct TProcDesc { ui32 ProcId = 0; TString Name; TString Src; TString Descr; TVector ArgTypes; TVector InputArgNames; ui32 ResultType = 0; bool IsStrict = true; EProcKind Kind = EProcKind::Function; bool ReturnSet = false; TVector OutputArgNames; TVector OutputArgTypes; ui32 Lang = LangInternal; ui32 VariadicType = 0; ui32 VariadicArgType = 0; TString VariadicArgName; TVector> DefaultArgs; TExprNode* ExprNode = nullptr; ui32 ExtensionIndex = 0; }; // Copied from pg_collation_d.h constexpr ui32 InvalidCollationOid = 0; constexpr ui32 DefaultCollationOid = 100; constexpr ui32 C_CollationOid = 950; constexpr ui32 PosixCollationOid = 951; // Copied from pg_type_d.h, TYPTYPE_* constants enum class ETypType : char { Base = 'b', Composite = 'c', Domain = 'd', Enum = 'e', Multirange = 'm', Pseudo = 'p', Range = 'r', }; constexpr char InvalidCategory = '\0'; struct TTypeDesc { ui32 TypeId = 0; ui32 ArrayTypeId = 0; TString Descr; TString Name; ui32 ElementTypeId = 0; bool PassByValue = false; char Category = InvalidCategory; bool IsPreferred = false; char TypeAlign = '\0'; char TypeDelim = ','; /* * Collation: InvalidCollationOid if type cannot use collations, nonzero (typically * DefaultCollationOid) for collatable base types, possibly some other * OID for domains over collatable types */ ui32 TypeCollation = InvalidCollationOid; ui32 InFuncId = 0; ui32 OutFuncId = 0; ui32 SendFuncId = 0; ui32 ReceiveFuncId = 0; ui32 TypeModInFuncId = 0; ui32 TypeModOutFuncId = 0; ui32 TypeSubscriptFuncId = 0; i32 TypeLen = 0; // from opclass ui32 LessProcId = 0; ui32 EqualProcId = 0; ui32 CompareProcId = 0; ui32 HashProcId = 0; // If TypType is 'c', typrelid is the OID of the class' entry in pg_class. ETypType TypType = ETypType::Base; ui32 ExtensionIndex = 0; }; enum class ECastMethod { Function, InOut, Binary }; enum class ECoercionCode : char { Unknown = '?', // not specified Implicit = 'i', // coercion in context of expression Assignment = 'a', // coercion in context of assignment Explicit = 'e', // explicit cast operation }; struct TCastDesc { ui32 SourceId = 0; ui32 TargetId = 0; ECastMethod Method = ECastMethod::Function; ui32 FunctionId = 0; ECoercionCode CoercionCode = ECoercionCode::Unknown; ui32 ExtensionIndex = 0; }; enum class EAggKind : char { Normal = 'n', OrderedSet = 'o', Hypothetical = 'h' }; struct TAggregateDesc { ui32 AggId = 0; TString Name; TVector ArgTypes; EAggKind Kind = EAggKind::Normal; ui32 TransTypeId = 0; ui32 TransFuncId = 0; ui32 FinalFuncId = 0; ui32 CombineFuncId = 0; ui32 SerializeFuncId = 0; ui32 DeserializeFuncId = 0; TString InitValue; bool FinalExtra = false; ui32 NumDirectArgs = 0; ui32 ExtensionIndex = 0; }; enum class EAmType { Table = 't', Index = 'i' }; struct TAmDesc { ui32 Oid = 0; TString Descr; TString AmName; EAmType AmType = EAmType::Index; }; struct TNamespaceDesc { ui32 Oid = 0; TString Name; TString Descr; }; enum class EOpClassMethod { Btree, Hash }; struct TOpFamilyDesc { TString Name; ui32 FamilyId = 0; ui32 ExtensionIndex = 0; }; struct TOpClassDesc { EOpClassMethod Method = EOpClassMethod::Btree; ui32 TypeId = 0; TString Name; TString Family; ui32 FamilyId = 0; ui32 ExtensionIndex = 0; }; struct TAmOpDesc { TString Family; ui32 FamilyId = 0; ui32 Strategy = 0; ui32 LeftType = 0; ui32 RightType = 0; ui32 OperId = 0; ui32 ExtensionIndex = 0; }; enum class EBtreeAmStrategy { Less = 1, LessOrEqual = 2, Equal = 3, GreaterOrEqual = 4, Greater = 5 }; struct TAmProcDesc { TString Family; ui32 FamilyId = 0; ui32 ProcNum = 0; ui32 LeftType = 0; ui32 RightType = 0; ui32 ProcId = 0; ui32 ExtensionIndex = 0; }; enum class EBtreeAmProcNum { Compare = 1 }; enum class EHashAmProcNum { Hash = 1 }; struct TConversionDesc { ui32 ConversionId = 0; TString From; TString To; TString Descr; ui32 ProcId = 0; }; struct TLanguageDesc { ui32 LangId = 0; TString Name; TString Descr; }; const TProcDesc& LookupProc(const TString& name, const TVector& argTypeIds); const TProcDesc& LookupProc(ui32 procId, const TVector& argTypeIds); const TProcDesc& LookupProc(ui32 procId); std::variant LookupProcWithCasts(const TString& name, const TVector& argTypeIds); bool HasReturnSetProc(const TString& name); void EnumProc(std::function f); bool HasProc(const TString& name, EProcKind kind); bool HasType(const TString& name); bool HasType(ui32 typeId); const TTypeDesc& LookupType(const TString& name); const TTypeDesc& LookupType(ui32 typeId); TMaybe LookupCommonType(const TVector& typeIds, const std::function& GetPosition, const TTypeDesc*& typeDesc); TMaybe LookupCommonType(const TVector& typeIds, const std::function& GetPosition, const TTypeDesc*& typeDesc, bool& castsNeeded); void EnumTypes(std::function f); const TAmDesc& LookupAm(ui32 oid); void EnumAm(std::function f); void EnumConversions(std::function f); const TNamespaceDesc& LookupNamespace(ui32 oid); void EnumNamespace(std::function f); void EnumOperators(std::function f); bool HasCast(ui32 sourceId, ui32 targetId); const TCastDesc& LookupCast(ui32 sourceId, ui32 targetId); const TOperDesc& LookupOper(const TString& name, const TVector& argTypeIds); const TOperDesc& LookupOper(ui32 operId, const TVector& argTypeIds); const TOperDesc& LookupOper(ui32 operId); bool HasAggregation(const TString& name, EAggKind kind); const TAggregateDesc& LookupAggregation(const TString& name, const TVector& argTypeIds); const TAggregateDesc& LookupAggregation(const TString& name, ui32 stateType, ui32 resultType); void EnumAggregation(std::function f); bool HasOpClass(EOpClassMethod method, ui32 typeId); const TOpClassDesc* LookupDefaultOpClass(EOpClassMethod method, ui32 typeId); bool HasAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType); const TAmOpDesc& LookupAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType); bool HasAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType); const TAmProcDesc& LookupAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType); bool HasConversion(const TString& from, const TString& to); const TConversionDesc& LookupConversion(const TString& from, const TString& to); const TLanguageDesc& LookupLanguage(ui32 langId); void EnumLanguages(std::function f); bool IsCompatibleTo(ui32 actualType, ui32 expectedType); bool IsCoercible(ui32 fromTypeId, ui32 toTypeId, ECoercionCode coercionType); inline bool IsArrayType(const TTypeDesc& typeDesc) noexcept { return typeDesc.ArrayTypeId == typeDesc.TypeId; } enum class ERelKind : char { Relation = 'r', View = 'v' }; struct TTableInfoKey { TString Schema; TString Name; bool operator==(const TTableInfoKey& other) const { return Schema == other.Schema && Name == other.Name; } bool operator<(const TTableInfoKey& other) const { return std::tie(Schema, Name) < std::tie(other.Schema, other.Name); } size_t Hash() const { auto stringHasher = THash(); return CombineHashes(stringHasher(Schema), stringHasher(Name)); } }; constexpr ui32 TypeRelationOid = 1247; constexpr ui32 DatabaseRelationOid = 1262; constexpr ui32 TableSpaceRelationOid = 1213; constexpr ui32 SharedDescriptionRelationOid = 2396; constexpr ui32 TriggerRelationOid = 2620; constexpr ui32 InheritsRelationOid = 2611; constexpr ui32 DescriptionRelationOid = 2609; constexpr ui32 AccessMethodRelationOid = 2601; constexpr ui32 NamespaceRelationOid = 2615; constexpr ui32 AuthMemRelationOid = 1261; constexpr ui32 RelationRelationOid = 1259; struct TTableInfo : public TTableInfoKey { ERelKind Kind; ui32 Oid; ui32 ExtensionIndex = 0; }; struct TColumnInfo { TString Schema; TString TableName; TString Name; TString UdtType; ui32 ExtensionIndex = 0; }; const TVector& GetStaticTables(); const TTableInfo& LookupStaticTable(const TTableInfoKey& tableKey); const THashMap>& GetStaticColumns(); const TVector>* ReadTable( const TTableInfoKey& tableKey, const TVector& columnNames, size_t* columnsRemap, // should have the same length as columnNames size_t& rowStep); bool AreAllFunctionsAllowed(); void AllowFunction(const TString& name); struct TExtensionDesc { TString Name; // postgis TString InstallName; // $libdir/postgis-3 TVector SqlPaths; // paths to SQL files with DDL (CREATE TYPE/CREATE FUNCTION/etc), DML (INSERT/VALUES) TString LibraryPath; // file path bool TypesOnly = false; // Can't be loaded if true TString LibraryMD5; // optional TString Version; // version of extension }; class IExtensionSqlBuilder { public: virtual ~IExtensionSqlBuilder() = default; virtual void CreateProc(const TProcDesc& desc) = 0; virtual void PrepareType(ui32 extensionIndex,const TString& name) = 0; virtual void UpdateType(const TTypeDesc& desc) = 0; virtual void CreateTable(const TTableInfo& table, const TVector& columns) = 0; virtual void InsertValues(const TTableInfoKey& table, const TVector& columns, const TVector>& data) = 0; // row based layout virtual void CreateCast(const TCastDesc& desc) = 0; virtual void PrepareOper(ui32 extensionIndex, const TString& name, const TVector& args) = 0; virtual void UpdateOper(const TOperDesc& desc) = 0; virtual void CreateAggregate(const TAggregateDesc& desc) = 0; virtual void CreateOpClass(const TOpClassDesc& opclass, const TVector& ops, const TVector& procs) = 0; }; class IExtensionSqlParser { public: virtual ~IExtensionSqlParser() = default; virtual void Parse(ui32 extensionIndex, const TVector& sqls, IExtensionSqlBuilder& builder) = 0; }; class IExtensionLoader { public: virtual ~IExtensionLoader() = default; virtual void Load(ui32 extensionIndex, const TString& name, const TString& path) = 0; }; class ISystemFunctionsParser { public: virtual ~ISystemFunctionsParser() = default; virtual void Parse(const TString& sql, TVector& procs) const = 0; }; class ISqlLanguageParser { public: virtual ~ISqlLanguageParser() = default; virtual void Parse(const TString& sql, TProcDesc& proc) = 0; virtual void ParseNode(const Node* stmt, TProcDesc& proc) = 0; virtual void Freeze() = 0; virtual TExprContext& GetContext() = 0; }; void SetSqlLanguageParser(std::unique_ptr parser); ISqlLanguageParser* GetSqlLanguageParser(); void LoadSystemFunctions(ISystemFunctionsParser& parser); // either RegisterExtensions or ImportExtensions should be called at most once, see ClearExtensions as well void RegisterExtensions(const TVector& extensions, bool typesOnly, IExtensionSqlParser& parser, IExtensionLoader* loader); // converts all library paths to basenames TString ExportExtensions(const TMaybe>& filter = Nothing()); void ImportExtensions(const TString& exported, bool typesOnly, IExtensionLoader* loader); void ClearExtensions(); void EnumExtensions(std::function f); const TExtensionDesc& LookupExtension(ui32 extensionIndex); ui32 LookupExtensionByName(const TString& name); ui32 LookupExtensionByInstallName(const TString& installName); } template <> inline void Out(IOutputStream& o, NYql::NPg::ETypType typType) { o.Write(static_cast::type>(typType)); } template <> inline void Out(IOutputStream& o, NYql::NPg::ECoercionCode coercionCode) { o.Write(static_cast::type>(coercionCode)); } template <> struct THash { size_t operator ()(const NYql::NPg::TTableInfoKey& val) const { return val.Hash(); } };