{-# LANGUAGE TemplateHaskell #-} -- | -- Working example: -- -- \$ curl -XPOST http://localhost:8080/v2/query -d @- < BigQueryRunSQL -> m EncJSON runSQL = runSQL_ recordSetAsHeaderAndRows -- | The SQL query in the request is ignored runDatabaseInspection :: (MonadIO m, CacheRWM m, MonadError QErr m, MetadataM m) => BigQueryRunSQL -> m EncJSON runDatabaseInspection (BigQueryRunSQL _query source) = do BigQuerySourceConfig {_scDatasets = dataSets} <- askSourceConfig @'BigQuery source let queries = [ "SELECT *, ARRAY(SELECT as STRUCT * from " <> getBigQueryDataset dataSet <> ".INFORMATION_SCHEMA.COLUMNS WHERE table_name = t.table_name) as columns from " <> getBigQueryDataset dataSet <> ".INFORMATION_SCHEMA.TABLES as t" | dataSet <- dataSets ] query' = T.intercalate " UNION ALL " queries runSQL_ recordSetAsSchema (BigQueryRunSQL query' source) runSQL_ :: (MonadIO m, CacheRWM m, MonadError QErr m, MetadataM m) => (Execute.RecordSet -> J.Value) -> BigQueryRunSQL -> m EncJSON runSQL_ f (BigQueryRunSQL query source) = do sourceConfig <- askSourceConfig @'BigQuery source result <- Execute.streamBigQuery (_scConnection sourceConfig) Execute.BigQuery {query = LT.fromStrict query, parameters = mempty} case result of Left executeProblem -> do let errorMessage = Execute.executeProblemMessage Execute.HideDetails executeProblem throwError (err400 BigQueryError errorMessage) {qeInternal = Just $ ExtraInternal $ J.toJSON executeProblem} Right recordSet -> pure ( encJFromJValue (RunSQLRes "TuplesOk" (f (snd recordSet))) ) recordSetAsHeaderAndRows :: Execute.RecordSet -> J.Value recordSetAsHeaderAndRows Execute.RecordSet {rows} = J.toJSON (thead : tbody) where thead = case rows V.!? 0 of Nothing -> [] Just row -> map (J.toJSON . (coerce :: Execute.FieldNameText -> Text)) (InsOrdHashMap.keys row) tbody :: [[J.Value]] tbody = map (map J.toJSON . InsOrdHashMap.elems) (toList rows) recordSetAsSchema :: Execute.RecordSet -> J.Value recordSetAsSchema rs@(Execute.RecordSet {rows}) = recordSetAsHeaderAndRows $ rs { Execute.rows = InsOrdHashMap.adjust (Execute.TextOutputValue . LT.toStrict . encodeToLazyText . J.toJSON) (Execute.FieldNameText "columns") <$> rows }