mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-20 06:58:39 +03:00
Customization of computed field GraphQL schema descriptions
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3615 GitOrigin-RevId: f51590d4cfc0412be9baa371353f9b9f3b908f84
This commit is contained in:
parent
6c7820caa0
commit
2c7a4e3a16
@ -19,6 +19,9 @@ The optimization can be enabled using the
|
||||
`--experimental-features=optimize_permission_filters` flag or the
|
||||
`HASURA_GRAPHQL_EXPERIMENTAL_FEATURES` environment variable.
|
||||
|
||||
### Breaking changes
|
||||
* Computed field comments are now used as the description for the field in the GraphQL schema. This means that computed fields where the comment has been set to empty string will cause the description of the field in the GraphQL schema to also be blank. Setting the computed field comment to null will restore the previous auto-generated description. The previous version of the Console would set the comment to empty string if the comment textbox was left blank, so some existing computed fields may unintentionally have empty string set as their comment.
|
||||
|
||||
### Bug fixes and improvements
|
||||
(Add entries below in the order of server, console, cli, docs, others)
|
||||
|
||||
@ -26,7 +29,7 @@ The optimization can be enabled using the
|
||||
- server: fix nullable action response (issue #4405)
|
||||
- console: add support for remote database relationships
|
||||
- console: enable support for update permissions for mssql #3591
|
||||
- server: add support for customization of table GraphQL schema descriptions (#7496)
|
||||
- server: add support for customization of table & computed field GraphQL schema descriptions (#7496)
|
||||
- cli: skip tls verfication for all API requests when `insecure-skip-tls-verify` flag is set (#4926)
|
||||
- server: classify MSSQL exceptions and improve API error responses
|
||||
|
||||
|
@ -141,6 +141,10 @@ export const isArrayString = (str: string) => {
|
||||
return false;
|
||||
};
|
||||
|
||||
export function emptyStringToNull(val?: string): string | null {
|
||||
return val && val !== '' ? val : null;
|
||||
}
|
||||
|
||||
/* ARRAY utils */
|
||||
export const deleteArrayElementAtIndex = (array: unknown[], index: number) => {
|
||||
return array.splice(index, 1);
|
||||
|
@ -2,7 +2,10 @@ import React from 'react';
|
||||
import AceEditor from 'react-ace';
|
||||
import { OptionTypeBase } from 'react-select';
|
||||
|
||||
import { getConfirmation } from '../../../Common/utils/jsUtils';
|
||||
import {
|
||||
emptyStringToNull,
|
||||
getConfirmation,
|
||||
} from '../../../Common/utils/jsUtils';
|
||||
import ExpandableEditor from '../../../Common/Layout/ExpandableEditor/Editor';
|
||||
import RawSqlButton from '../Common/Components/RawSqlButton';
|
||||
import Tooltip from '../../../Common/Tooltip/Tooltip';
|
||||
@ -274,7 +277,7 @@ const ComputedFieldsEditor: React.FC<ComputedFieldsEditorProps> = ({
|
||||
|
||||
newState[i] = {
|
||||
...newState[i],
|
||||
comment: e.target.value,
|
||||
comment: emptyStringToNull(e.target.value),
|
||||
};
|
||||
|
||||
setComputedFieldsState(newState);
|
||||
|
@ -90,8 +90,10 @@ Args syntax
|
||||
- The computed field definition
|
||||
* - comment
|
||||
- false
|
||||
- text
|
||||
- comment
|
||||
- ``String``
|
||||
- Customise the description shown in GraphQL introspection. If null or omitted then
|
||||
if a comment exists on the database function, it is used as the description, and
|
||||
if not, an autogenerated description is used instead.
|
||||
* - source
|
||||
- false
|
||||
- :ref:`SourceName <SourceName>`
|
||||
@ -156,4 +158,3 @@ Args syntax
|
||||
- false
|
||||
- :ref:`SourceName <SourceName>`
|
||||
- Name of the source database of the table (default: ``default``)
|
||||
|
||||
|
@ -36,7 +36,7 @@ buildComputedFieldInfo ::
|
||||
ComputedFieldName ->
|
||||
ComputedFieldDefinition 'BigQuery ->
|
||||
RawFunctionInfo 'BigQuery ->
|
||||
Maybe Text ->
|
||||
Comment ->
|
||||
m (ComputedFieldInfo 'BigQuery)
|
||||
buildComputedFieldInfo _ _ _ _ _ _ =
|
||||
throw400 NotSupported "Computed fields aren't supported for BigQuery sources"
|
||||
|
@ -43,7 +43,7 @@ buildComputedFieldInfo ::
|
||||
ComputedFieldName ->
|
||||
ComputedFieldDefinition 'MSSQL ->
|
||||
RawFunctionInfo 'MSSQL ->
|
||||
Maybe Text ->
|
||||
Comment ->
|
||||
m (ComputedFieldInfo 'MSSQL)
|
||||
buildComputedFieldInfo _ _ _ _ _ _ =
|
||||
throw400 NotSupported "Computed fields aren't supported for MSSQL sources"
|
||||
|
@ -16,6 +16,7 @@ import Hasura.Backends.Postgres.DDL.Function
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
import Hasura.Base.Error
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Common (Comment (..))
|
||||
import Hasura.RQL.Types.ComputedField
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.SQL.Backend
|
||||
@ -85,7 +86,7 @@ buildComputedFieldInfo ::
|
||||
ComputedFieldName ->
|
||||
ComputedFieldDefinition ('Postgres pgKind) ->
|
||||
PGRawFunctionInfo ->
|
||||
Maybe Text ->
|
||||
Comment ->
|
||||
m (ComputedFieldInfo ('Postgres pgKind))
|
||||
buildComputedFieldInfo trackedTables table computedField definition rawFunctionInfo comment =
|
||||
either (throw400 NotSupported . showErrors) pure =<< MV.runValidateT mkComputedFieldInfo
|
||||
@ -169,7 +170,7 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
|
||||
ComputedFieldFunction function inputArgSeq tableArgument maybePGSessionArg $
|
||||
rfiDescription rawFunctionInfo
|
||||
|
||||
pure $ ComputedFieldInfo @('Postgres pgKind) () computedField computedFieldFunction returnType comment
|
||||
pure $ ComputedFieldInfo @('Postgres pgKind) () computedField computedFieldFunction returnType description
|
||||
|
||||
validateTableArgumentType ::
|
||||
(MV.MonadValidate [ComputedFieldValidateError] n) =>
|
||||
@ -215,3 +216,13 @@ buildComputedFieldInfo trackedTables table computedField definition rawFunctionI
|
||||
Just (FunctionSessionArgument name _) ->
|
||||
filter ((/=) (Just name) . faName) withoutTable
|
||||
in alsoWithoutSession
|
||||
|
||||
description :: Maybe Text
|
||||
description =
|
||||
case comment of
|
||||
Automatic -> commentFromDatabase <|> Just autogeneratedDescription
|
||||
Explicit value -> toTxt <$> value
|
||||
where
|
||||
commentFromDatabase = getPGDescription <$> rfiDescription rawFunctionInfo
|
||||
autogeneratedDescription =
|
||||
"A computed field, executes function " <>> function
|
||||
|
@ -1356,7 +1356,7 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable selectPermissions
|
||||
caseBoolExpUnpreparedValue
|
||||
)
|
||||
dummyParser <- lift $ columnParser @('Postgres pgKind) (ColumnScalar scalarReturnType) (G.Nullability True)
|
||||
pure $ P.selection fieldName (Just fieldDescription) fieldArgsParser dummyParser
|
||||
pure $ P.selection fieldName fieldDescription fieldArgsParser dummyParser
|
||||
CFRSetofTable tableName -> do
|
||||
tableInfo <- lift $ askTableInfo sourceName tableName
|
||||
remotePerms <- MaybeT $ tableSelectPermissions tableInfo
|
||||
@ -1364,7 +1364,7 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable selectPermissions
|
||||
selectionSetParser <- lift $ P.multiple . P.nonNullableParser <$> tableSelectionSet sourceName tableInfo remotePerms
|
||||
let fieldArgsParser = liftA2 (,) functionArgsParser selectArgsParser
|
||||
pure $
|
||||
P.subselection fieldName (Just fieldDescription) fieldArgsParser selectionSetParser
|
||||
P.subselection fieldName fieldDescription fieldArgsParser selectionSetParser
|
||||
<&> \((functionArgs', args), fields) ->
|
||||
IR.AFComputedField _cfiXComputedFieldInfo _cfiName $
|
||||
IR.CFSTable JASMultipleRows $
|
||||
@ -1376,9 +1376,8 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable selectPermissions
|
||||
IR._asnStrfyNum = stringifyNum
|
||||
}
|
||||
where
|
||||
fieldDescription =
|
||||
let defaultDescription = "A computed field, executes function " <>> _cffName _cfiFunction
|
||||
in mkDescriptionWith (_cffDescription _cfiFunction) defaultDescription
|
||||
fieldDescription :: Maybe G.Description
|
||||
fieldDescription = G.Description <$> _cfiDescription
|
||||
|
||||
computedFieldFunctionArgs ::
|
||||
ComputedFieldFunction ('Postgres pgKind) ->
|
||||
|
@ -25,7 +25,7 @@ data AddComputedField b = AddComputedField
|
||||
_afcTable :: !(TableName b),
|
||||
_afcName :: !ComputedFieldName,
|
||||
_afcDefinition :: !(ComputedFieldDefinition b),
|
||||
_afcComment :: !(Maybe Text)
|
||||
_afcComment :: !Comment
|
||||
}
|
||||
deriving stock (Generic)
|
||||
|
||||
@ -39,7 +39,7 @@ instance (Backend b) => FromJSON (AddComputedField b) where
|
||||
<*> o .: "table"
|
||||
<*> o .: "name"
|
||||
<*> o .: "definition"
|
||||
<*> o .:? "comment"
|
||||
<*> o .:? "comment" .!= Automatic
|
||||
|
||||
runAddComputedField ::
|
||||
forall b m.
|
||||
|
@ -194,12 +194,13 @@ addComputedFieldToCatalog q =
|
||||
defaultTxErrorHandler
|
||||
[Q.sql|
|
||||
INSERT INTO hdb_catalog.hdb_computed_field
|
||||
(table_schema, table_name, computed_field_name, definition, comment)
|
||||
(table_schema, table_name, computed_field_name, definition, commentText)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
|]
|
||||
(schemaName, tableName, computedField, Q.AltJ definition, comment)
|
||||
(schemaName, tableName, computedField, Q.AltJ definition, commentText)
|
||||
True
|
||||
where
|
||||
commentText = commentToMaybeText comment
|
||||
QualifiedObject schemaName tableName = table
|
||||
AddComputedField _ table computedField definition comment = q
|
||||
|
||||
@ -575,7 +576,7 @@ fetchMetadataFromHdbTables = liftTx do
|
||||
pure $
|
||||
flip map r $ \(schema, table, name, Q.AltJ definition, comment) ->
|
||||
( QualifiedObject schema table,
|
||||
ComputedFieldMetadata name definition comment
|
||||
ComputedFieldMetadata name definition (commentFromMaybeText comment)
|
||||
)
|
||||
|
||||
fetchCronTriggers =
|
||||
|
@ -43,6 +43,9 @@ module Hasura.RQL.Types.Common
|
||||
PGConnectionParams (..),
|
||||
getPGConnectionStringFromParams,
|
||||
getConnOptionsFromConnParams,
|
||||
Comment (..),
|
||||
commentToMaybeText,
|
||||
commentFromMaybeText,
|
||||
)
|
||||
where
|
||||
|
||||
@ -50,6 +53,7 @@ import Control.Lens (makeLenses)
|
||||
import Data.Aeson
|
||||
import Data.Aeson.Casing
|
||||
import Data.Aeson.TH
|
||||
import Data.Aeson.Types (prependFailure, typeMismatch)
|
||||
import Data.Bifunctor (bimap)
|
||||
import Data.Environment qualified as Env
|
||||
import Data.Scientific (toBoundedInteger)
|
||||
@ -487,3 +491,36 @@ $(deriveJSON (aesonPrefix snakeCase) ''MetricsConfig)
|
||||
|
||||
emptyMetricsConfig :: MetricsConfig
|
||||
emptyMetricsConfig = MetricsConfig False False
|
||||
|
||||
data Comment
|
||||
= -- | Automatically generate a comment (derive it from DB comments, or a sensible default describing the source of the data)
|
||||
Automatic
|
||||
| -- | The user's explicitly provided comment, or explicitly no comment (ie. leave it blank, do not autogenerate one)
|
||||
Explicit (Maybe NonEmptyText)
|
||||
deriving (Eq, Show, Generic)
|
||||
|
||||
instance NFData Comment
|
||||
|
||||
instance Cacheable Comment
|
||||
|
||||
instance Hashable Comment
|
||||
|
||||
instance FromJSON Comment where
|
||||
parseJSON = \case
|
||||
Null -> pure Automatic
|
||||
String text -> pure . Explicit $ mkNonEmptyText text
|
||||
val -> prependFailure "parsing Comment failed, " (typeMismatch "String or Null" val)
|
||||
|
||||
instance ToJSON Comment where
|
||||
toJSON Automatic = Null
|
||||
toJSON (Explicit (Just value)) = String (toTxt value)
|
||||
toJSON (Explicit Nothing) = String ""
|
||||
|
||||
commentToMaybeText :: Comment -> Maybe Text
|
||||
commentToMaybeText Automatic = Nothing
|
||||
commentToMaybeText (Explicit Nothing) = Just ""
|
||||
commentToMaybeText (Explicit (Just val)) = Just (toTxt val)
|
||||
|
||||
commentFromMaybeText :: Maybe Text -> Comment
|
||||
commentFromMaybeText Nothing = Automatic
|
||||
commentFromMaybeText (Just val) = Explicit $ mkNonEmptyText val
|
||||
|
@ -10,7 +10,7 @@ module Hasura.RQL.Types.ComputedField
|
||||
FunctionSessionArgument (..),
|
||||
FunctionTableArgument (..),
|
||||
FunctionTrackedAs (..),
|
||||
cfiComment,
|
||||
cfiDescription,
|
||||
cfiFunction,
|
||||
cfiName,
|
||||
cfiReturnType,
|
||||
@ -28,7 +28,7 @@ import Data.Aeson
|
||||
import Data.Aeson.Casing
|
||||
import Data.Sequence qualified as Seq
|
||||
import Data.Text.Extended
|
||||
import Data.Text.NonEmpty
|
||||
import Data.Text.NonEmpty (NonEmptyText (..))
|
||||
import Database.PG.Query qualified as Q
|
||||
import Hasura.Backends.Postgres.SQL.Types hiding (FunctionName, TableName)
|
||||
import Hasura.Incremental (Cacheable)
|
||||
@ -177,7 +177,7 @@ data ComputedFieldInfo (b :: BackendType) = ComputedFieldInfo
|
||||
_cfiName :: !ComputedFieldName,
|
||||
_cfiFunction :: !(ComputedFieldFunction b),
|
||||
_cfiReturnType :: !(ComputedFieldReturn b),
|
||||
_cfiComment :: !(Maybe Text)
|
||||
_cfiDescription :: !(Maybe Text)
|
||||
}
|
||||
deriving (Generic)
|
||||
|
||||
@ -193,8 +193,8 @@ instance (Backend b) => Hashable (ComputedFieldInfo b)
|
||||
|
||||
instance (Backend b) => ToJSON (ComputedFieldInfo b) where
|
||||
-- spelling out the JSON instance in order to skip the Trees That Grow field
|
||||
toJSON (ComputedFieldInfo _ name func tp comment) =
|
||||
object ["name" .= name, "function" .= func, "return_type" .= tp, "comment" .= comment]
|
||||
toJSON (ComputedFieldInfo _ name func tp description) =
|
||||
object ["name" .= name, "function" .= func, "return_type" .= tp, "description" .= description]
|
||||
|
||||
$(makeLenses ''ComputedFieldInfo)
|
||||
|
||||
|
@ -197,17 +197,26 @@ currentMetadataVersion = MVVersion3
|
||||
data ComputedFieldMetadata b = ComputedFieldMetadata
|
||||
{ _cfmName :: !ComputedFieldName,
|
||||
_cfmDefinition :: !(ComputedFieldDefinition b),
|
||||
_cfmComment :: !(Maybe Text)
|
||||
_cfmComment :: !Comment
|
||||
}
|
||||
deriving (Show, Eq, Generic)
|
||||
|
||||
instance (Backend b) => Cacheable (ComputedFieldMetadata b)
|
||||
|
||||
instance (Backend b) => ToJSON (ComputedFieldMetadata b) where
|
||||
toJSON = genericToJSON hasuraJSON
|
||||
toJSON ComputedFieldMetadata {..} =
|
||||
object
|
||||
[ "name" .= _cfmName,
|
||||
"definition" .= _cfmDefinition,
|
||||
"comment" .= _cfmComment
|
||||
]
|
||||
|
||||
instance (Backend b) => FromJSON (ComputedFieldMetadata b) where
|
||||
parseJSON = genericParseJSON hasuraJSON
|
||||
parseJSON = withObject "ComputedFieldMetadata" $ \obj ->
|
||||
ComputedFieldMetadata
|
||||
<$> obj .: "name"
|
||||
<*> obj .: "definition"
|
||||
<*> obj .:? "comment" .!= Automatic
|
||||
|
||||
data RemoteSchemaPermissionMetadata = RemoteSchemaPermissionMetadata
|
||||
{ _rspmRole :: !RoleName,
|
||||
@ -931,7 +940,7 @@ metadataToOrdJSON
|
||||
[ ("name", AO.toOrdered name),
|
||||
("definition", AO.toOrdered definition)
|
||||
]
|
||||
<> catMaybes [maybeCommentToMaybeOrdPair comment]
|
||||
<> catMaybes [commentToMaybeOrdPair comment]
|
||||
|
||||
insPermDefToOrdJSON :: forall b. (Backend b) => InsPermDef b -> AO.Value
|
||||
insPermDefToOrdJSON = permDefToOrdJSON insPermToOrdJSON
|
||||
@ -1256,6 +1265,9 @@ metadataToOrdJSON
|
||||
maybeAnyToMaybeOrdPair :: Text -> (a -> AO.Value) -> Maybe a -> Maybe (Text, AO.Value)
|
||||
maybeAnyToMaybeOrdPair name f = fmap ((name,) . f)
|
||||
|
||||
commentToMaybeOrdPair :: Comment -> Maybe (Text, AO.Value)
|
||||
commentToMaybeOrdPair comment = (\val -> ("comment", AO.toOrdered val)) <$> commentToMaybeText comment
|
||||
|
||||
instance ToJSON Metadata where
|
||||
toJSON = AO.fromOrdered . metadataToOrdJSON
|
||||
|
||||
|
@ -37,7 +37,7 @@ class
|
||||
ComputedFieldName ->
|
||||
ComputedFieldDefinition b ->
|
||||
RawFunctionInfo b ->
|
||||
Maybe Text ->
|
||||
Comment ->
|
||||
m (ComputedFieldInfo b)
|
||||
|
||||
fetchAndValidateEnumValues ::
|
||||
|
@ -7,7 +7,6 @@ module Hasura.RQL.Types.Table
|
||||
DBTableMetadata (..),
|
||||
DBTablesMetadata,
|
||||
DelPermInfo (..),
|
||||
Comment (..),
|
||||
FieldInfo (..),
|
||||
FieldInfoMap,
|
||||
ForeignKey (..),
|
||||
@ -85,7 +84,6 @@ import Control.Lens hiding ((.=))
|
||||
import Data.Aeson.Casing
|
||||
import Data.Aeson.Extended
|
||||
import Data.Aeson.TH
|
||||
import Data.Aeson.Types (prependFailure, typeMismatch)
|
||||
import Data.HashMap.Strict qualified as M
|
||||
import Data.HashMap.Strict.Extended qualified as M
|
||||
import Data.HashSet qualified as HS
|
||||
@ -94,7 +92,6 @@ import Data.List.NonEmpty qualified as NE
|
||||
import Data.Semigroup (Any (..), Max (..))
|
||||
import Data.Text qualified as T
|
||||
import Data.Text.Extended
|
||||
import Data.Text.NonEmpty (NonEmptyText, mkNonEmptyText)
|
||||
import Hasura.Backends.Postgres.SQL.Types qualified as PG (PGDescription)
|
||||
import Hasura.Base.Error
|
||||
import Hasura.Incremental (Cacheable)
|
||||
@ -581,28 +578,6 @@ isMutable f (Just vi) = f vi
|
||||
|
||||
type CustomColumnNames b = HashMap (Column b) G.Name
|
||||
|
||||
data Comment
|
||||
= -- | Automatically generate a comment (derive it from DB comments, or a sensible default describing the source of the data)
|
||||
Automatic
|
||||
| -- | The user's explicitly provided comment, no explicitly no comment (ie. leave it blank, do not autogenerate one)
|
||||
Explicit (Maybe NonEmptyText)
|
||||
deriving (Eq, Show, Generic)
|
||||
|
||||
instance NFData Comment
|
||||
|
||||
instance Cacheable Comment
|
||||
|
||||
instance FromJSON Comment where
|
||||
parseJSON = \case
|
||||
Null -> pure Automatic
|
||||
String text -> pure . Explicit $ mkNonEmptyText text
|
||||
val -> prependFailure "parsing Comment failed, " (typeMismatch "String or Null" val)
|
||||
|
||||
instance ToJSON Comment where
|
||||
toJSON Automatic = Null
|
||||
toJSON (Explicit (Just value)) = String (toTxt value)
|
||||
toJSON (Explicit Nothing) = String ""
|
||||
|
||||
data TableConfig b = TableConfig
|
||||
{ _tcCustomRootFields :: !TableCustomRootFields,
|
||||
_tcCustomColumnNames :: !(CustomColumnNames b),
|
||||
|
@ -1,9 +1,11 @@
|
||||
module Hasura.RQL.Types.CommonSpec (spec) where
|
||||
|
||||
import Data.Text qualified as Text
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Common (PGConnectionParams (..), getPGConnectionStringFromParams)
|
||||
import Hasura.RQL.Types.Common (PGConnectionParams (..), commentFromMaybeText, commentToMaybeText, getPGConnectionStringFromParams)
|
||||
import Network.URI (isAbsoluteURI)
|
||||
import Test.Hspec
|
||||
import Test.Hspec.QuickCheck (prop)
|
||||
|
||||
noPasswordParams :: PGConnectionParams
|
||||
noPasswordParams =
|
||||
@ -35,6 +37,7 @@ escapeCharParams =
|
||||
spec :: Spec
|
||||
spec = do
|
||||
pgConnectionStringFromParamsSpec
|
||||
commentSpec
|
||||
|
||||
pgConnectionStringFromParamsSpec :: Spec
|
||||
pgConnectionStringFromParamsSpec =
|
||||
@ -56,3 +59,11 @@ pgConnectionStringFromParamsSpec =
|
||||
|
||||
connectionString `shouldBe` "postgresql://r00t:p%40ssw0rd@loc%40lhost:5432/test%2F%2Fdb"
|
||||
isAbsoluteURI connectionString `shouldBe` True
|
||||
|
||||
commentSpec :: Spec
|
||||
commentSpec =
|
||||
describe "Comment" $ do
|
||||
prop "should roundtrip between Comment and Maybe Text" $
|
||||
\str ->
|
||||
let text = Text.pack <$> str
|
||||
in (commentToMaybeText . commentFromMaybeText) text `shouldBe` text
|
||||
|
@ -8,6 +8,10 @@ query:
|
||||
name
|
||||
description
|
||||
kind
|
||||
fields {
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
response:
|
||||
@ -16,3 +20,10 @@ query:
|
||||
name: automatic_comment_in_db
|
||||
description: What a great comment in the DB
|
||||
kind: OBJECT
|
||||
fields:
|
||||
- name: id
|
||||
description: null
|
||||
- name: name
|
||||
description: null
|
||||
- name: upper_name
|
||||
description: What a great comment on the function in the DB
|
||||
|
@ -8,6 +8,10 @@ query:
|
||||
name
|
||||
description
|
||||
kind
|
||||
fields {
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
response:
|
||||
@ -16,3 +20,10 @@ query:
|
||||
name: automatic_no_comment_in_db
|
||||
description: columns and relationships of "automatic_no_comment_in_db"
|
||||
kind: OBJECT
|
||||
fields:
|
||||
- name: id
|
||||
description: null
|
||||
- name: name
|
||||
description: null
|
||||
- name: upper_name
|
||||
description: A computed field, executes function automatic_no_comment_in_db_upper_name
|
||||
|
@ -8,6 +8,10 @@ query:
|
||||
name
|
||||
description
|
||||
kind
|
||||
fields {
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
response:
|
||||
@ -16,3 +20,10 @@ query:
|
||||
name: explicit_comment_in_metadata
|
||||
description: Such an explicit comment, wow
|
||||
kind: OBJECT
|
||||
fields:
|
||||
- name: id
|
||||
description: null
|
||||
- name: name
|
||||
description: null
|
||||
- name: upper_name
|
||||
description: Such an explicit function comment, wow
|
||||
|
@ -8,6 +8,10 @@ query:
|
||||
name
|
||||
description
|
||||
kind
|
||||
fields {
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
response:
|
||||
@ -16,3 +20,10 @@ query:
|
||||
name: explicit_no_comment_in_metadata
|
||||
description: null
|
||||
kind: OBJECT
|
||||
fields:
|
||||
- name: id
|
||||
description: null
|
||||
- name: name
|
||||
description: null
|
||||
- name: upper_name
|
||||
description: null
|
||||
|
@ -5,29 +5,64 @@ args:
|
||||
args:
|
||||
sql: |
|
||||
CREATE TABLE "automatic_comment_in_db" (
|
||||
id serial primary key
|
||||
id serial primary key,
|
||||
name text not null
|
||||
);
|
||||
COMMENT ON TABLE "automatic_comment_in_db" IS 'What a great comment in the DB';
|
||||
CREATE FUNCTION automatic_comment_in_db_upper_name(r "automatic_comment_in_db")
|
||||
RETURNS text
|
||||
LANGUAGE 'sql'
|
||||
STABLE
|
||||
AS $BODY$
|
||||
SELECT upper(r.name)
|
||||
$BODY$;
|
||||
COMMENT ON FUNCTION "automatic_comment_in_db_upper_name"("automatic_comment_in_db") IS 'What a great comment on the function in the DB';
|
||||
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
CREATE TABLE "automatic_no_comment_in_db" (
|
||||
id serial primary key
|
||||
id serial primary key,
|
||||
name text not null
|
||||
);
|
||||
CREATE FUNCTION automatic_no_comment_in_db_upper_name(r "automatic_no_comment_in_db")
|
||||
RETURNS text
|
||||
LANGUAGE 'sql'
|
||||
STABLE
|
||||
AS $BODY$
|
||||
SELECT upper(r.name)
|
||||
$BODY$;
|
||||
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
CREATE TABLE "explicit_comment_in_metadata" (
|
||||
id serial primary key
|
||||
id serial primary key,
|
||||
name text not null
|
||||
);
|
||||
COMMENT ON TABLE "explicit_comment_in_metadata" IS 'Fantastic comment, so good, so hidden';
|
||||
CREATE FUNCTION explicit_comment_in_metadata_upper_name(r "explicit_comment_in_metadata")
|
||||
RETURNS text
|
||||
LANGUAGE 'sql'
|
||||
STABLE
|
||||
AS $BODY$
|
||||
SELECT upper(r.name)
|
||||
$BODY$;
|
||||
COMMENT ON FUNCTION "explicit_comment_in_metadata_upper_name"("explicit_comment_in_metadata") IS 'Fantastic comment on the function, so good, so hidden';
|
||||
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
CREATE TABLE "explicit_no_comment_in_metadata" (
|
||||
id serial primary key
|
||||
id serial primary key,
|
||||
name text not null
|
||||
);
|
||||
COMMENT ON TABLE "explicit_no_comment_in_metadata" IS 'This would be a great comment, but you can''t see it';
|
||||
CREATE FUNCTION explicit_no_comment_in_metadata_upper_name(r "explicit_no_comment_in_metadata")
|
||||
RETURNS text
|
||||
LANGUAGE 'sql'
|
||||
STABLE
|
||||
AS $BODY$
|
||||
SELECT upper(r.name)
|
||||
$BODY$;
|
||||
COMMENT ON FUNCTION "explicit_no_comment_in_metadata_upper_name"("explicit_no_comment_in_metadata") IS 'This would be a great comment on the function, but you can''t see it';
|
||||
|
@ -1,7 +1,11 @@
|
||||
type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
DROP FUNCTION "automatic_comment_in_db_upper_name"("automatic_comment_in_db");
|
||||
DROP TABLE "automatic_comment_in_db" cascade;
|
||||
DROP FUNCTION "automatic_no_comment_in_db_upper_name"("automatic_no_comment_in_db");
|
||||
DROP TABLE "automatic_no_comment_in_db" cascade;
|
||||
DROP FUNCTION "explicit_comment_in_metadata_upper_name"("explicit_comment_in_metadata");
|
||||
DROP TABLE "explicit_comment_in_metadata" cascade;
|
||||
DROP FUNCTION "explicit_no_comment_in_metadata_upper_name"("explicit_no_comment_in_metadata");
|
||||
DROP TABLE "explicit_no_comment_in_metadata" cascade;
|
||||
|
@ -4,18 +4,48 @@ args:
|
||||
args:
|
||||
table: automatic_comment_in_db
|
||||
|
||||
- type: pg_add_computed_field
|
||||
args:
|
||||
table: automatic_comment_in_db
|
||||
name: upper_name
|
||||
definition:
|
||||
function: automatic_comment_in_db_upper_name
|
||||
|
||||
- type: pg_track_table
|
||||
args:
|
||||
table: automatic_no_comment_in_db
|
||||
|
||||
- type: pg_add_computed_field
|
||||
args:
|
||||
table: automatic_no_comment_in_db
|
||||
name: upper_name
|
||||
definition:
|
||||
function: automatic_no_comment_in_db_upper_name
|
||||
|
||||
- type: pg_track_table
|
||||
args:
|
||||
table: explicit_comment_in_metadata
|
||||
configuration:
|
||||
comment: Such an explicit comment, wow
|
||||
|
||||
- type: pg_add_computed_field
|
||||
args:
|
||||
table: explicit_comment_in_metadata
|
||||
name: upper_name
|
||||
definition:
|
||||
function: explicit_comment_in_metadata_upper_name
|
||||
comment: Such an explicit function comment, wow
|
||||
|
||||
- type: pg_track_table
|
||||
args:
|
||||
table: explicit_no_comment_in_metadata
|
||||
configuration:
|
||||
comment: ""
|
||||
|
||||
- type: pg_add_computed_field
|
||||
args:
|
||||
table: explicit_no_comment_in_metadata
|
||||
name: upper_name
|
||||
definition:
|
||||
function: explicit_no_comment_in_metadata_upper_name
|
||||
comment: ""
|
||||
|
Loading…
Reference in New Issue
Block a user