@metabase/cli 0.3.1 → 0.3.2-alpha.fix-transform-test-ee-path.8ac2a7a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-collection-CYDUm_XO.mjs → add-collection-B_-eMU_k.mjs} +6 -9
- package/dist/{alert-ClyhtxIz.mjs → alert-Dalin_DD.mjs} +7 -7
- package/dist/{alerts-Dt3D1gcz.mjs → alerts-DpBgrjPI.mjs} +7 -7
- package/dist/{append-Bl_Ensmr.mjs → append-C1JNVALm.mjs} +5 -5
- package/dist/{archive-BOyKhNOz.mjs → archive-52ZHbFDm2.mjs} +6 -6
- package/dist/{archive-DiGxCojL.mjs → archive-B51prFgS.mjs} +4 -4
- package/dist/{archive-CWceyy8x.mjs → archive-BkITQyWW.mjs} +5 -5
- package/dist/{archive-BJZ7Dace.mjs → archive-CISXgZAI.mjs} +6 -6
- package/dist/{archive-D3a3Wgz0.mjs → archive-CdKf_Eqq.mjs} +4 -4
- package/dist/{archive-DVGDg8mP.mjs → archive-CicPYX27.mjs} +6 -6
- package/dist/{archive-CNblz55j.mjs → archive-CwITzj_j.mjs} +6 -6
- package/dist/{archive-DSMqHRr1.mjs → archive-DA3OiLEE.mjs} +4 -4
- package/dist/{archive-nKD3mOB8.mjs → archive-DVHxeDKS.mjs} +6 -6
- package/dist/{archive-BdHXQg4I.mjs → archive-DckxlWBt.mjs} +4 -4
- package/dist/{archive-DDru3vdy.mjs → archive-cAdUa1-2.mjs} +4 -4
- package/dist/{auth-aCksg8q2.mjs → auth-A96JOCQx.mjs} +5 -5
- package/dist/{body-DxRSAMNC.mjs → body-CshgcV6U.mjs} +3 -3
- package/dist/{branches-_0VWR2Zm.mjs → branches-CbcwWYL9.mjs} +4 -7
- package/dist/{cancel-ctpVE8uC.mjs → cancel-DpDcVY7M.mjs} +4 -4
- package/dist/{cancel-task-FtxBka-M.mjs → cancel-task-B4RDvIYb.mjs} +5 -8
- package/dist/{card-zyUkr2nS.mjs → card-CEkp1mcI.mjs} +1 -1
- package/dist/card-CefVYtF7.mjs +24 -0
- package/dist/{card-DZxRmver.mjs → card-voh1k4hl.mjs} +14 -11
- package/dist/{cards-DHOWAvfv.mjs → cards-BC0JX8Yg.mjs} +7 -7
- package/dist/cli.mjs +582 -69
- package/dist/client-ClL6gf7G.mjs +3783 -0
- package/dist/collection-Be5AHVWP.mjs +20 -0
- package/dist/{collection-CfulNRBG.mjs → collection-BxdPxD38.mjs} +1 -1
- package/dist/{collection-CGoVLvcD.mjs → collection-DYM0p3Xl.mjs} +1 -1
- package/dist/{collection-namespace-CEoQ7G08.mjs → collection-namespace-Dv0l-V9K.mjs} +2 -2
- package/dist/{content-translation-DNKerjS3.mjs → content-translation-BXIXL4eW.mjs} +3 -3
- package/dist/{create-DmvoibX8.mjs → create--fiwuTWc.mjs} +4 -4
- package/dist/{create-CLG2-bso.mjs → create-B9qXQ_wV.mjs} +6 -6
- package/dist/{create-CEydRMWS.mjs → create-BVNhtAgF.mjs} +7 -7
- package/dist/{create-C9vy4ZG6.mjs → create-BbjSOTN-.mjs} +5 -5
- package/dist/{create-BdPVWYSi.mjs → create-BcsVwXgS2.mjs} +6 -6
- package/dist/{create-CcLchJAN.mjs → create-Bryrkb9g.mjs} +7 -7
- package/dist/{create-7ddYK4TA.mjs → create-CHr8MPPq.mjs} +6 -6
- package/dist/{create-DaYRnK5P.mjs → create-D--Z1S3p2.mjs} +8 -8
- package/dist/{create-F4Lf09xq.mjs → create-DWFJdyIr.mjs} +4 -4
- package/dist/{create-vlrlY-2E.mjs → create-Dhai9zAt.mjs} +4 -4
- package/dist/create-DiJ8bUb-.mjs +34 -0
- package/dist/{create-C78g8Crb.mjs → create-DmN2gFc4.mjs} +5 -5
- package/dist/{create-wJR4CxHA.mjs → create-NCKHHdov.mjs} +5 -8
- package/dist/{create-C3IaXXty.mjs → create-YetX69Re.mjs} +4 -4
- package/dist/{create-e650zxzX.mjs → create-Za1EskpV.mjs} +5 -5
- package/dist/{create-branch-B8C7jl-J.mjs → create-branch-CseVn3lp.mjs} +5 -9
- package/dist/{create-DIVhBIyE.mjs → create-kZIIEN2Y.mjs} +11 -7
- package/dist/{csv-BLPJtlSC.mjs → csv-DNzesu8y.mjs} +5 -5
- package/dist/{current-task-C-ldJbWE.mjs → current-task-DRTKZcP9.mjs} +5 -8
- package/dist/{dashboard-CtO_3EfC.mjs → dashboard-CMw13KXM.mjs} +10 -10
- package/dist/{dashboard-CKUR8ZpQ.mjs → dashboard-D0hwTC-f.mjs} +11 -2
- package/dist/{dashboard-BlbNszi8.mjs → dashboard-DgK81azj.mjs} +1 -1
- package/dist/{database-B19qlLKZ.mjs → database-C3E9PZSx.mjs} +1 -1
- package/dist/{database-C8G6ZKG0.mjs → database-JtHTqSpq.mjs} +1 -1
- package/dist/{db-xXselnBq.mjs → db-BDijt81U.mjs} +7 -7
- package/dist/{delete-BZZHw6pm.mjs → delete--15it-A8.mjs} +5 -5
- package/dist/delete-Bsdwqh7H.mjs +44 -0
- package/dist/{delete-ZJJyqsRh.mjs → delete-BudvZkvK.mjs} +5 -5
- package/dist/{delete-BwSPQy7m.mjs → delete-BxjJ66BS.mjs} +5 -5
- package/dist/{delete-BZwAOQxG.mjs → delete-Dc8E5YwZ.mjs} +5 -5
- package/dist/{delete-runtime-D74s6vhu.mjs → delete-runtime-BKEzJn22.mjs} +1 -2
- package/dist/{delete-table-CJktZE3w.mjs → delete-table-5AQpn8OB.mjs} +5 -5
- package/dist/{delete-D6WxgWRp.mjs → delete-wFsy80db.mjs} +5 -5
- package/dist/{dependencies-BdqIqEIy.mjs → dependencies-C1ogC3BV.mjs} +7 -7
- package/dist/{dirty-BW2As2wS.mjs → dirty-CSLDYO-K.mjs} +6 -9
- package/dist/document-BGzVip5_.mjs +19 -0
- package/dist/{document-Cd2mmqCp.mjs → document-BHpLJbKU.mjs} +5 -0
- package/dist/{document-D6OybtP2.mjs → document-CA0Q6lqu.mjs} +1 -1
- package/dist/{download-mfFJ9oRS.mjs → download-Ddap1OAo.mjs} +3 -6
- package/dist/{eid-DZ-4t2xe.mjs → eid-HnrWhPoe.mjs} +4 -5
- package/dist/{events-D6yFmXP1.mjs → events-CXqetjcS.mjs} +5 -5
- package/dist/{export-DYZjz1WP.mjs → export-IFZdgYZ2.mjs} +7 -10
- package/dist/{field-BJ54wmIX.mjs → field-BJ6HoLRd.mjs} +5 -5
- package/dist/{field-Cr2DPUG9.mjs → field-CcN4oZy6.mjs} +16 -1
- package/dist/{field-BPsNa-TO.mjs → field-fDtIrY6D.mjs} +1 -1
- package/dist/{fields-FUWCgPOa.mjs → fields-DxHxuxwO.mjs} +7 -7
- package/dist/{get-ByZJf9nO.mjs → get-B2pj2q3X.mjs} +5 -5
- package/dist/{get-C_5AbfpO.mjs → get-BF2vdF3W.mjs} +4 -4
- package/dist/{get-DAOSGt5Z.mjs → get-BGLvyOO3.mjs} +6 -6
- package/dist/{get-DMECsioX.mjs → get-BcoJ9Aha.mjs} +4 -4
- package/dist/{get-CsN7NBI0.mjs → get-BiPclcIP.mjs} +4 -4
- package/dist/{get-DCutQeiV.mjs → get-C3cuZNeW.mjs} +4 -4
- package/dist/{get-CQ0-fFWP.mjs → get-CDnmpfHQ.mjs} +5 -8
- package/dist/{get-DRJtsS1_.mjs → get-CE9_4Q7E.mjs} +4 -4
- package/dist/{get-C5q49Dgx.mjs → get-C_tdSMwW2.mjs} +6 -6
- package/dist/{get-CWnriw33.mjs → get-CxUQyhte.mjs} +6 -6
- package/dist/{get-DVyesErX.mjs → get-DW7mCaGe.mjs} +6 -6
- package/dist/{get-DYaQpixt.mjs → get-D_x-ENFe.mjs} +6 -6
- package/dist/{get-Ba2HRdrx.mjs → get-DjlQhgD4.mjs} +6 -6
- package/dist/{get-DhkltKIV.mjs → get-DmKtPNOy.mjs} +4 -4
- package/dist/{get-BWl3vzsf.mjs → get-Dtre5jzh.mjs} +6 -6
- package/dist/get-H6kInHIx.mjs +93 -0
- package/dist/{get-BraVQ1FJ.mjs → get-b0CoPz5B.mjs} +6 -6
- package/dist/{get-LAew34ID.mjs → get-eJilYnHk.mjs} +6 -6
- package/dist/get-i0KInCw9.mjs +32 -0
- package/dist/{get-_ggLr1tY.mjs → get-jofVjU6e.mjs} +6 -6
- package/dist/{get-run-oH4dRCBx.mjs → get-run-BE1HtJDW.mjs} +6 -6
- package/dist/{git-sync-BDnxPrqU.mjs → git-sync-BwBRmEhE.mjs} +18 -1
- package/dist/{git-sync-DxD_ng48.mjs → git-sync-TjX1r_wF.mjs} +1 -1
- package/dist/git-sync-xKC1sqC4.mjs +28 -0
- package/dist/{group-DBM87IgC.mjs → group-YQQ5GIcP.mjs} +2 -2
- package/dist/{has-remote-changes-CnmyIw_7.mjs → has-remote-changes-Cj1KhBOT.mjs} +5 -8
- package/dist/{import-B7Si-bSI.mjs → import-DLb9VN4l.mjs} +7 -10
- package/dist/{input-DH9i67x_.mjs → input-D5tQEfqN.mjs} +1 -1
- package/dist/{is-dirty-BOH_VEA8.mjs → is-dirty-BxtgV2xF.mjs} +3 -6
- package/dist/{items-DouHkWev.mjs → items-DLUYc5-z.mjs} +7 -7
- package/dist/{key-BEhqIzIQ.mjs → key-PYetuQ13.mjs} +1 -1
- package/dist/{library-1J_4Dicw.mjs → library-BNSxXOpc.mjs} +5 -5
- package/dist/library-BPIzb3K_.mjs +81 -0
- package/dist/{library-DfYAT2Ep.mjs → library-PGCfm0UA.mjs} +1 -1
- package/dist/{list-D25ofn4v.mjs → list-B1soS8QW.mjs} +7 -7
- package/dist/{list-Cy0w4Fap.mjs → list-BQnOEB3W.mjs} +4 -4
- package/dist/{list-BeMYIeiI.mjs → list-BUz6KOfw.mjs} +7 -7
- package/dist/{list-C1bAtgO1.mjs → list-BcP1DTJH.mjs} +4 -4
- package/dist/{list-DJK9_BEF.mjs → list-C5mS_ehX.mjs} +14 -13
- package/dist/{list-qs9wAtC3.mjs → list-CBLxhaNZ.mjs} +4 -4
- package/dist/{list-aKUk-a1Y.mjs → list-CERbeLbQ.mjs} +7 -7
- package/dist/{list-B2Ddf4W0.mjs → list-COLpwXW4.mjs} +5 -5
- package/dist/{list-sDpy4nDU.mjs → list-CQbiSx26.mjs} +6 -6
- package/dist/{list-C0zJ2ehz.mjs → list-CX9qZ-bx.mjs} +6 -6
- package/dist/{list-DhViDVx_.mjs → list-CehE6KBV.mjs} +6 -6
- package/dist/list-Cuhf2lKL.mjs +35 -0
- package/dist/{list-D2IYZ6lk.mjs → list-CzRzCbCY.mjs} +6 -6
- package/dist/{list-DWLGpMvr.mjs → list-D-SyhKFw.mjs} +7 -7
- package/dist/{list-DptEWB5Y.mjs → list-Dat8QNcf.mjs} +4 -4
- package/dist/{list-C7UvO3Uw.mjs → list-M8J10Ozk.mjs} +6 -6
- package/dist/{list-BXlTYsYA.mjs → list-Sd7jGZoX.mjs} +4 -4
- package/dist/list-cIMww2Me.mjs +60 -0
- package/dist/{list-BK_6VNm_.mjs → list-jhQSgh6i.mjs} +4 -4
- package/dist/{login-BmyCAfRV.mjs → login-BfLqBfCd.mjs} +18 -15
- package/dist/{logout-DUR32q0V.mjs → logout-BpRXB3Ze.mjs} +3 -4
- package/dist/{measure-DdVp-8jw.mjs → measure-Ds8O5Evr.mjs} +6 -6
- package/dist/{notification-Fcq1fIPw.mjs → notification-DVrLkjFT.mjs} +1 -1
- package/dist/{parameter-DUKR8NXo.mjs → parameter-Celg0wZa.mjs} +1 -1
- package/dist/{parameter-values-CBR-cBev.mjs → parameter-values-DhrkLXoN.mjs} +5 -6
- package/dist/{parse-enum-D0Jfm_Bz.mjs → parse-enum-Dc0dMZ3P.mjs} +1 -1
- package/dist/{parse-id-B3YwNojT.mjs → parse-id-DtM6q9HU.mjs} +1 -1
- package/dist/{parse-ref-ibKVB0J4.mjs → parse-ref-DTDld_LJ.mjs} +1 -1
- package/dist/{path-D8BQmEhL.mjs → path-_GHFrTLx.mjs} +5 -5
- package/dist/{poll-75SvT7Zv.mjs → poll-KLl4Eq8Y.mjs} +2 -2
- package/dist/{preflight-CoF1Em99.mjs → preflight-BpYtF0IU.mjs} +3 -4
- package/dist/{process-DBOOrmET.mjs → process-CLtOWKBn.mjs} +1 -1
- package/dist/{publish-Cb7XrQ3X.mjs → publish-D-7Zlmuk.mjs} +9 -9
- package/dist/{pulse-BmsDenXm.mjs → pulse-Dz0ocv0l.mjs} +1 -1
- package/dist/{pulse-DhG6I9mI.mjs → pulse-x0gFxWfG.mjs} +2 -2
- package/dist/{query-D35B588l.mjs → query-B1CZztxs.mjs} +10 -12
- package/dist/query-CxESKMve.mjs +114 -0
- package/dist/{query-result-DBDwk8TS.mjs → query-result-E4Q-Gra6.mjs} +1 -1
- package/dist/{remove-collection-DJem6V26.mjs → remove-collection-C4saCFxz.mjs} +6 -9
- package/dist/{render-CI93iP0I.mjs → render-6O_eF-P1.mjs} +13 -2
- package/dist/{replace-CtsWICrD.mjs → replace-BuR4f2Ai.mjs} +5 -5
- package/dist/{rescan-values-CaXUL6z5.mjs → rescan-values-CNOiiWQ5.mjs} +6 -6
- package/dist/{run-CM-Amtbf.mjs → run-DijA_BXt.mjs} +26 -14
- package/dist/run-FmRruANb.mjs +64 -0
- package/dist/{run-BeLm17F4.mjs → run-QEUbWNm7.mjs} +9 -9
- package/dist/{runs-DFG63zgr.mjs → runs-BSlhVeDO.mjs} +7 -7
- package/dist/{runtime-z8rra6-I.mjs → runtime-Dtb93zKy.mjs} +994 -252
- package/dist/{schema-tables-COAHkIcy.mjs → schema-tables-BE3rEb6I.mjs} +7 -7
- package/dist/{schemas-BX5BATiV.mjs → schemas-yDjBiwlH.mjs} +5 -5
- package/dist/{search-DFBwUc6d.mjs → search-BAXg-EJw.mjs} +2 -1
- package/dist/{search-CPvvmhdt.mjs → search-CR_xNArA.mjs} +6 -6
- package/dist/{segment-C62L6BI3.mjs → segment-Cm6zQjJW.mjs} +6 -6
- package/dist/{selectors-P4QnrORk.mjs → selectors-C-vgMcGK.mjs} +3 -3
- package/dist/{send-PZh5IKF8.mjs → send-kC8oerkT.mjs} +4 -4
- package/dist/{set-active-DL4QzWDO.mjs → set-active-lDKhAlij.mjs} +5 -5
- package/dist/{set-DbCtUoFd.mjs → set-tFhPkxrL.mjs} +5 -5
- package/dist/{setting-BlRcZbhC.mjs → setting-DrJXCaFE.mjs} +4 -4
- package/dist/{setup-D_SLaC-3.mjs → setup-BWY9M0iR.mjs} +4 -4
- package/dist/{signal-CMd0EFUa.mjs → signal-Csom0mt5.mjs} +11 -2
- package/dist/skill-list-CCes8pKe.mjs +76 -0
- package/dist/skills-DE9ej5Rg.mjs +351 -0
- package/dist/{skills-D991LB1M.mjs → skills-DPRN2384.mjs} +3 -3
- package/dist/snippet-DWHTSo9c.mjs +19 -0
- package/dist/{stash-DyBxFoP6.mjs → stash-C9oDvQ9P.mjs} +7 -11
- package/dist/{status-DUsiogz5.mjs → status-CkpujA26.mjs} +11 -9
- package/dist/{status-cfDHqK2Q.mjs → status-DSdXmNC3.mjs} +12 -11
- package/dist/{subscription-Bn0AU7GN.mjs → subscription-DKOKoHRG.mjs} +6 -6
- package/dist/{subscriptions-DwqjCVlc.mjs → subscriptions-C5SyJL4B.mjs} +7 -7
- package/dist/{summary-BGwSNzf4.mjs → summary-DTPgXsc0.mjs} +6 -6
- package/dist/{sync-schema-dtkDOAKe.mjs → sync-schema-DKKkNSR7.mjs} +7 -7
- package/dist/{sync-task-BACcrs0i.mjs → sync-task-BtDnTXCP.mjs} +3 -2
- package/dist/{table-CsIJNPFf.mjs → table-C6h4tIRw.mjs} +1 -1
- package/dist/{table-CeeTJgQb.mjs → table-DfuY0N8e.mjs} +51 -4
- package/dist/{table-BJoEAoCU.mjs → table-I8NXSdUC.mjs} +5 -5
- package/dist/timeline-B_ESH-6W.mjs +21 -0
- package/dist/{timeline-event-BsF7YqzZ.mjs → timeline-event-n4Lzet7l.mjs} +6 -6
- package/dist/transform-BNuNiH9d.mjs +28 -0
- package/dist/{transform-DoTyyXAu.mjs → transform-CtqB1WYo.mjs} +2 -2
- package/dist/{transform-D3QX0jxA.mjs → transform-DiW7bREn.mjs} +68 -5
- package/dist/{transform-job-50GZHhKH.mjs → transform-job-AaMZRxAq.mjs} +1 -1
- package/dist/transform-job-B7yc6dfH.mjs +22 -0
- package/dist/{transform-job-DRrK28IH.mjs → transform-job-CCguL6LP.mjs} +41 -4
- package/dist/{transform-tag-VM9R7Q_M.mjs → transform-tag-D6NXqWaX.mjs} +5 -5
- package/dist/transform-test-BjjCQ2xm.mjs +169 -0
- package/dist/transform-test-C1Oqtfb-.mjs +16 -0
- package/dist/transform-test-gzDcbypy.mjs +25 -0
- package/dist/{transforms-BjACGbBp.mjs → transforms-O4NtXqFz.mjs} +7 -7
- package/dist/transport-CyVo29u7.mjs +313 -0
- package/dist/{tree-BwS6JAmk.mjs → tree-CuyF116R.mjs} +4 -5
- package/dist/{unpublish-DWdPnENY.mjs → unpublish-DvWefKJi.mjs} +4 -7
- package/dist/{update-DkviXwSg.mjs → update-2KIpYgyj.mjs} +7 -7
- package/dist/{update-DKEHY-gt.mjs → update-76nzOc71.mjs} +7 -7
- package/dist/{update-B2CF2DK4.mjs → update-7oKvP1HC.mjs} +6 -6
- package/dist/{update-DTmRHBik.mjs → update-AJ2JmwDl.mjs} +7 -7
- package/dist/{update-BR_vkkd1.mjs → update-BB6Go_RX.mjs} +5 -5
- package/dist/{update-DCjAjihm.mjs → update-Bah7N8QX.mjs} +6 -6
- package/dist/{update-cqR1U6DU.mjs → update-CGJvIS-l.mjs} +5 -5
- package/dist/{update-tLIhVIPp.mjs → update-D7dG7H-z.mjs} +8 -8
- package/dist/{update-C1FBVLfC.mjs → update-DOdcflLH.mjs} +8 -8
- package/dist/{update-DlTaD1x3.mjs → update-DV54H3L5.mjs} +9 -9
- package/dist/{update-C4y3iQsv.mjs → update-DXmZuJho.mjs} +7 -7
- package/dist/{update-3idz42uD.mjs → update-DmgRIp7o.mjs} +7 -7
- package/dist/{update-DsZttiSC.mjs → update-H_fdjugs.mjs} +5 -5
- package/dist/{update-BCT9qpVr.mjs → update-To6A1Ugu.mjs} +5 -5
- package/dist/{update-dashcard-DlE_bb2F.mjs → update-dashcard-DjT5QOkL.mjs} +7 -7
- package/dist/update-l3PyNQKG.mjs +41 -0
- package/dist/{update-BpPaacCF.mjs → update-xEegxIyH.mjs} +6 -6
- package/dist/{upgrade-mNV7XuJG.mjs → upgrade-CuJx9fX4.mjs} +6 -8
- package/dist/upload-2YFFBSln.mjs +13 -0
- package/dist/{upload-CEGVxmYB.mjs → upload-CboARPZm.mjs} +4 -7
- package/dist/{upload-CD555ui1.mjs → upload-DOO94rCQ.mjs} +2 -2
- package/dist/{uuid-C4hqn3kA.mjs → uuid-InwZlrpQ.mjs} +10 -7
- package/dist/{validate-BWchyW0V.mjs → validate-D6-Vg_kn.mjs} +69 -23
- package/dist/{validate-query-DaGYSmpQ.mjs → validate-query-B90KYPQr.mjs} +3 -4
- package/dist/{values-C0O3eNaW.mjs → values-CsZLk1Ls.mjs} +6 -6
- package/dist/{verify-DfTjYF7s.mjs → verify-DrGjZwBM.mjs} +3 -18
- package/dist/{wait-WZmFenN_.mjs → wait-BmzdarP9.mjs} +7 -10
- package/dist/{wait-flags-BbfDSP8R.mjs → wait-flags-CiJGrTCT.mjs} +2 -2
- package/dist/{window-BkvrP0gB.mjs → window-DSb1tqSe.mjs} +1 -1
- package/package.json +1 -1
- package/skill-data/core/SKILL.md +31 -15
- package/skill-data/dashboard/SKILL.md +1 -1
- package/skill-data/data-workflow/references/building-clean-tables.md +6 -2
- package/skill-data/data-workflow/references/reusable-definitions.md +11 -3
- package/skill-data/document/SKILL.md +4 -1
- package/skill-data/git-sync/SKILL.md +5 -0
- package/skill-data/mbql/SKILL.md +84 -115
- package/skill-data/mbql/references/operators.md +77 -231
- package/skill-data/metadata/SKILL.md +1 -1
- package/skill-data/metadata/references/semantic-types.md +7 -1
- package/skill-data/native-sql/SKILL.md +8 -9
- package/skill-data/native-sql/references/template-tags.md +27 -27
- package/skill-data/notification/SKILL.md +7 -1
- package/skill-data/transform/SKILL.md +76 -4
- package/skill-data/transform-test-plan/SKILL.md +171 -0
- package/skill-data/transform-test-plan/references/checklist.md +81 -0
- package/skill-data/transform-test-plan/references/checks.md +263 -0
- package/skill-data/visualization/SKILL.md +13 -6
- package/skill-data/visualization/references/settings.md +13 -11
- package/skills/metabase-cli/SKILL.md +1 -1
- package/dist/card-CGCXbdmD.mjs +0 -24
- package/dist/client-mKuHg_sc.mjs +0 -2218
- package/dist/collection-D8Tk8i3a.mjs +0 -20
- package/dist/document-KbcHhzFz.mjs +0 -19
- package/dist/get-BC8J8BXB.mjs +0 -80
- package/dist/git-sync-Dik8nKfw.mjs +0 -28
- package/dist/library-ClLgrAXy.mjs +0 -19
- package/dist/list-CW5PdYCX.mjs +0 -98
- package/dist/network-error-D6CiOEBw.mjs +0 -431
- package/dist/predicates-Bkm2IoeX.mjs +0 -170
- package/dist/query-C256WBYG.mjs +0 -87
- package/dist/skills-DTCrMcix.mjs +0 -216
- package/dist/snippet-DTDO55Cg.mjs +0 -19
- package/dist/timeline-DcXPshcT.mjs +0 -21
- package/dist/transform-Dsf_wHAj.mjs +0 -28
- package/dist/transform-job-B1yLv5l-.mjs +0 -22
- package/dist/upload-DsYCf5kB.mjs +0 -13
|
@@ -1,263 +1,109 @@
|
|
|
1
1
|
# MBQL operator reference
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
form. The clause _structure_ and the slot-1-options rule are in the SKILL.md body —
|
|
5
|
-
this file is the catalog of which operators exist and their arguments.
|
|
3
|
+
Every clause is `[op, {options}, ...args]` with `{}` when there are no options. `<field>` is `["field", {}, <field id>]`, or any expression of the right type; `<pred>` is a filter clause. Clause heads are lowercase and hyphenated, exactly as written here.
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
abbreviates the slot-1 options object — usually empty (`{}`), since `lib/uuid` is
|
|
9
|
-
optional and the server generates it (see the SKILL body). It carries a value only
|
|
10
|
-
when noted: an operator-specific option named in the row, or an explicit `lib/uuid`
|
|
11
|
-
you mint to reference the clause. Field refs are numeric: `["field", {…}, <field-id>]`.
|
|
12
|
-
Everything here passes `mb query --dry-run`; when in doubt, that loop is the authority.
|
|
5
|
+
## Filters
|
|
13
6
|
|
|
14
|
-
|
|
7
|
+
A stage's `filters` are ANDed.
|
|
15
8
|
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
- [
|
|
9
|
+
- `["and", {}, <pred>, <pred>, …]` / `["or", …]`: two or more
|
|
10
|
+
- `["not", {}, <pred>]`
|
|
11
|
+
- `["=", {}, <field>, <v1>, <v2>, …]` / `["!=", …]`: several values mean any of them / none of them
|
|
12
|
+
- `["in", {}, <field>, <v1>, <v2>, …]` / `["not-in", …]`: multi-value membership
|
|
13
|
+
- `["<", {}, <a>, <b>]` / `["<=", …]` / `[">", …]` / `[">=", …]`
|
|
14
|
+
- `["between", {}, <field>, <min>, <max>]`: inclusive; dates as `"2024-01-01"`
|
|
15
|
+
- `["inside", {}, <lat>, <lon>, <lat-max>, <lon-min>, <lat-min>, <lon-max>]`: bounding box
|
|
16
|
+
- `["is-null", {}, <field>]` / `["not-null", …]`
|
|
17
|
+
- `["is-empty", {}, <field>]` / `["not-empty", …]`: NULL or `""`
|
|
18
|
+
- `["contains", {}, <field>, "a", "b", …]` / `["does-not-contain", …]` / `["starts-with", …]` / `["ends-with", …]`: any of the strings (`does-not-contain`: none of them); `{"case-sensitive": false}` in options
|
|
19
|
+
- `["time-interval", {}, <field>, <n>, "<unit>"]`: the `n` whole units before the current one (`n` negative) or after it, or `"current"` / `"last"` / `"next"` for a single unit; `{"include-current": true}` in options adds the current unit
|
|
20
|
+
- `["relative-time-interval", {}, <field>, <n>, "<unit>", <offset n>, "<offset unit>"]`: a window shifted from now: last 3 months, a year ago
|
|
21
|
+
- `["during", {}, <field>, "2024-03-15", "<unit>"]`: the whole unit containing the date
|
|
22
|
+
- `["segment", {}, <segment id>]`: a saved segment, on its table
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
> (below). `relative-datetime` / `absolute-datetime` literals (e.g. from a UI-built
|
|
25
|
-
> query) also work.
|
|
24
|
+
Units for `time-interval` and friends: `millisecond`, `second`, `minute`, `hour`, `day`, `week`, `month`, `quarter`, `year`.
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
## Aggregations
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
- `["count", {}]` / `["count", {}, <field>]`: rows / non-NULL values
|
|
29
|
+
- `["sum", {}, <field>]` / `["avg", …]` / `["median", …]` / `["stddev", …]` / `["var", …]`: numeric
|
|
30
|
+
- `["min", {}, <field>]` / `["max", …]`: any orderable
|
|
31
|
+
- `["distinct", {}, <field>]`: count of distinct values
|
|
32
|
+
- `["percentile", {}, <field>, 0.9]`: 0 to 1
|
|
33
|
+
- `["count-where", {}, <pred>]`
|
|
34
|
+
- `["sum-where", {}, <field>, <pred>]`
|
|
35
|
+
- `["distinct-where", {}, <field>, <pred>]`
|
|
36
|
+
- `["share", {}, <pred>]`: fraction of rows, 0 to 1
|
|
37
|
+
- `["cum-count", {}]` / `["cum-sum", {}, <field>]`: running totals over the breakout
|
|
38
|
+
- `["offset", {}, <aggregation>, <n>]`: the value n breakout rows back (negative) or ahead; in `aggregation` only
|
|
39
|
+
- `["metric", {}, <card id>]`: a saved metric, on its table
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
`["or", {…}, …]` for OR.
|
|
41
|
+
<!-- requires: measures -->
|
|
33
42
|
|
|
34
|
-
|
|
43
|
+
`["measure", {}, <measure id>]` is a saved measure, on its table.
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
| ----- | ------------------ | ----------------------------------------------------- |
|
|
38
|
-
| `and` | 2+ boolean clauses | Logical AND (usually implicit via the `filters` list) |
|
|
39
|
-
| `or` | 2+ boolean clauses | Logical OR |
|
|
40
|
-
| `not` | 1 boolean clause | Logical NOT |
|
|
45
|
+
<!-- /requires -->
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
Name the output in options: `["sum", {"name": "revenue", "display-name": "Revenue"}, <field>]`.
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
| ----------------- | -------------------------------------------------------- | ----------------------- |
|
|
46
|
-
| `=` | field, 1+ values | Multi-value = IN |
|
|
47
|
-
| `!=` | field, 1+ values | Multi-value = NOT IN |
|
|
48
|
-
| `<` `>` `<=` `>=` | 2 orderable | |
|
|
49
|
-
| `between` | field, min, max | Inclusive |
|
|
50
|
-
| `inside` | lat-field, lon-field, lat-max, lon-min, lat-min, lon-max | Geographic bounding box |
|
|
49
|
+
## Expressions
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
["between", {…}, ["field", {…}, 12], 10, 100]
|
|
54
|
-
["=", {…}, ["field", {…}, 7], "Widget", "Gadget"]
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Null / empty
|
|
58
|
-
|
|
59
|
-
| Op | Args | Notes |
|
|
60
|
-
| ----------- | ------------------- | --------------------- |
|
|
61
|
-
| `is-null` | 1 expression | |
|
|
62
|
-
| `not-null` | 1 expression | |
|
|
63
|
-
| `is-empty` | 1 string expression | NULL or `""` |
|
|
64
|
-
| `not-empty` | 1 string expression | not NULL and not `""` |
|
|
65
|
-
|
|
66
|
-
### String match
|
|
67
|
-
|
|
68
|
-
N-ary (multiple values OR'd). Accept a `case-sensitive` option (default `true`) in the
|
|
69
|
-
options object.
|
|
51
|
+
Named in `expressions` by `{"lib/expression-name": "<name>"}` in the options, or used inline anywhere a value goes.
|
|
70
52
|
|
|
71
|
-
|
|
72
|
-
| ------------------ | ----------------- |
|
|
73
|
-
| `contains` | field, 1+ strings |
|
|
74
|
-
| `does-not-contain` | field, 1+ strings |
|
|
75
|
-
| `starts-with` | field, 1+ strings |
|
|
76
|
-
| `ends-with` | field, 1+ strings |
|
|
53
|
+
**Math:** `["+", {}, a, b, …]`, `["-", …]`, `["*", …]`, `["/", …]` (always a float), `["abs", {}, x]`, `["ceil", …]`, `["floor", …]`, `["round", …]`, `["sqrt", …]`, `["exp", …]`, `["log", …]`, `["power", {}, base, exponent]`. `round` takes one argument and rounds to an integer.
|
|
77
54
|
|
|
78
|
-
|
|
79
|
-
["contains", { "case-sensitive": false }, ["field", {…}, 9], "widget"]
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Temporal
|
|
55
|
+
**Conversion:** `["integer", {}, <text or number>]`, `["float", {}, <text>]`, `["text", {}, <any>]`, `["date", {}, <text or datetime>]`, `["datetime", {}, <ISO text>]`, `["datetime", {"mode": "simple"}, <text>]`, `["datetime", {"mode": "unix-seconds"}, <number>]` (number modes `unix-seconds`, `unix-milliseconds`, `unix-microseconds`, `unix-nanoseconds`).
|
|
83
56
|
|
|
84
|
-
|
|
85
|
-
| ------------------------ | ---------------------------------------------------------- | --------------------------------------------------- |
|
|
86
|
-
| `time-interval` | temporal-field, n, unit | `n` = integer, or `"current"` / `"last"` / `"next"` |
|
|
87
|
-
| `relative-time-interval` | temporal-field, value, bucket, offset-value, offset-bucket | interval with offset |
|
|
57
|
+
**Text:** `["concat", {}, a, b, …]`, `["substring", {}, s, <start from 1>, <length>?]`, `["replace", {}, s, "find", "replacement"]`, `["regex-match-first", {}, s, "<regex>"]`, `["split-part", {}, s, "<delimiter>", <position from 1>]`, `["length", {}, s]`, `["trim", …]`, `["ltrim", …]`, `["rtrim", …]`, `["upper", …]`, `["lower", …]`, `["host", {}, <url>]`, `["domain", …]`, `["subdomain", …]`, `["path", …]`.
|
|
88
58
|
|
|
89
|
-
|
|
90
|
-
`month`, `quarter`, `year`.
|
|
59
|
+
**Conditional:** `["case", {}, [[<pred>, <value>], [<pred>, <value>]], <default>?]` (alias `if`), `["coalesce", {}, a, b, …]`.
|
|
91
60
|
|
|
92
61
|
```json
|
|
93
|
-
[
|
|
94
|
-
|
|
62
|
+
[
|
|
63
|
+
"case",
|
|
64
|
+
{ "lib/expression-name": "Tier" },
|
|
65
|
+
[
|
|
66
|
+
[[">", {}, ["field", {}, 14], 100], "Premium"],
|
|
67
|
+
[["<=", {}, ["field", {}, 14], 20], "Budget"]
|
|
68
|
+
],
|
|
69
|
+
"Standard"
|
|
70
|
+
]
|
|
95
71
|
```
|
|
96
72
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| Op | Args | Notes |
|
|
100
|
-
| --------- | ---------- | ------------------------- |
|
|
101
|
-
| `segment` | segment id | Reference a saved segment |
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## Aggregation functions
|
|
106
|
-
|
|
107
|
-
A stage's `aggregation` is a list of aggregation clauses.
|
|
108
|
-
|
|
109
|
-
| Op | Args | Notes |
|
|
110
|
-
| ----------------------- | -------------------------- | -------------------------------- |
|
|
111
|
-
| `count` | none, or 1 expression | with arg: count non-NULL |
|
|
112
|
-
| `sum` `avg` `min` `max` | 1 numeric/orderable | |
|
|
113
|
-
| `distinct` | 1 expression | count of distinct values |
|
|
114
|
-
| `cum-count` | none or 1 expression | running count |
|
|
115
|
-
| `cum-sum` | 1 numeric | running sum |
|
|
116
|
-
| `stddev` `var` `median` | 1 numeric | |
|
|
117
|
-
| `percentile` | numeric, p (0.0–1.0) | |
|
|
118
|
-
| `count-where` | 1 boolean clause | |
|
|
119
|
-
| `sum-where` | numeric, boolean clause | |
|
|
120
|
-
| `distinct-where` | expression, boolean clause | |
|
|
121
|
-
| `share` | 1 boolean clause | proportion 0–1 |
|
|
122
|
-
| `metric` | metric id | reference a saved metric card |
|
|
123
|
-
| `measure` | measure id | reference a saved measure (v59+) |
|
|
124
|
-
|
|
125
|
-
```json
|
|
126
|
-
["count", {…}]
|
|
127
|
-
["sum", {…}, ["field", {…}, 42]]
|
|
128
|
-
["count-where", {…}, [">", {…}, ["field", {…}, 42], 100]]
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
**Naming** — set `name` (warehouse column) and/or `display-name` (UI header) in the
|
|
132
|
-
options object: `["sum", { "name": "revenue", "display-name": "Revenue" }, …]`.
|
|
133
|
-
|
|
134
|
-
**Window function** — `offset` is only valid inside `aggregation`:
|
|
135
|
-
|
|
136
|
-
| Op | Args | Notes |
|
|
137
|
-
| -------- | ------------- | ------------------------------------------------- |
|
|
138
|
-
| `offset` | expression, n | value n rows before (negative) / after (positive) |
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## Expression operators
|
|
143
|
-
|
|
144
|
-
Used in `expressions` (named, via `lib/expression-name` in options) and inline.
|
|
73
|
+
**Dates:**
|
|
145
74
|
|
|
146
|
-
|
|
75
|
+
- `["now", {}]` / `["today", {}]`
|
|
76
|
+
- `["datetime-add", {}, <date>, <n>, "<unit>"]` / `["datetime-subtract", …]`: `n` an integer
|
|
77
|
+
- `["datetime-diff", {}, <from>, <to>, "<unit>"]`: units `second` … `year`; the way to subtract two dates
|
|
78
|
+
- `["interval", {}, <n>, "<unit>"]`: added to a date with `+`
|
|
79
|
+
- `["get-year", {}, <date>]` / `get-quarter` / `get-month` / `get-day` / `get-hour` / `get-minute` / `get-second`: an integer; a quarter is `1`–`4`
|
|
80
|
+
- `["get-week", {}, <date>]` / `["get-day-of-week", {}, <date>]`: a fourth argument `"iso"`, `"us"` or `"instance"` sets the week convention
|
|
81
|
+
- `["temporal-extract", {}, <date>, "<extract unit>"]`: `year-of-era`, `quarter-of-year`, `month-of-year`, `week-of-year-iso`, `week-of-year-us`, `week-of-year-instance`, `day-of-month`, `day-of-week`, `day-of-week-iso`, `hour-of-day`, `minute-of-hour`, `second-of-minute`
|
|
82
|
+
- `["month-name", {}, <1–12>]` / `["quarter-name", {}, <1–4>]` / `["day-name", {}, <1–7>]`
|
|
83
|
+
- `["convert-timezone", {}, <date>, "America/New_York", "<from tz>"?]`
|
|
84
|
+
- `["relative-datetime", {}, <n>, "<unit>"]` / `["relative-datetime", {}, "current"]`: a point relative to now, for comparisons
|
|
85
|
+
- `["absolute-datetime", {}, "2024-03-15T00:00:00", "<unit>"]`: the unit is required, `"default"` keeps the literal; a date literal (`"2024-03-15"`) takes a date unit (`day` … `year`) or `"default"`
|
|
147
86
|
|
|
148
|
-
|
|
149
|
-
| --- | ---------------------------------- | -------------------- |
|
|
150
|
-
| `+` | 2+ numeric, or temporal + interval | |
|
|
151
|
-
| `-` | 1+ numeric, or temporal − interval | unary = negation |
|
|
152
|
-
| `*` | 2+ numeric | |
|
|
153
|
-
| `/` | 2+ numeric | always returns float |
|
|
87
|
+
Add, subtract, diff and interval units: `millisecond` (not diff), `second`, `minute`, `hour`, `day`, `week`, `month`, `quarter`, `year`.
|
|
154
88
|
|
|
155
|
-
|
|
89
|
+
## Field option: `temporal-unit`
|
|
156
90
|
|
|
157
|
-
|
|
158
|
-
| ---------------------------- | -------------- |
|
|
159
|
-
| `abs` `ceil` `floor` `round` | 1 numeric |
|
|
160
|
-
| `power` | base, exponent |
|
|
161
|
-
| `sqrt` `exp` `log` | 1 numeric |
|
|
91
|
+
On a date field ref, mostly in `breakout`:
|
|
162
92
|
|
|
163
|
-
|
|
93
|
+
- Truncation: `minute`, `hour`, `day`, `week`, `month`, `quarter`, `year` (and `millisecond`, `second`).
|
|
94
|
+
- Extraction, an integer: `minute-of-hour`, `hour-of-day`, `day-of-week`, `day-of-month`, `day-of-year`, `week-of-year`, `month-of-year`, `quarter-of-year`, `year-of-era`, `second-of-minute`.
|
|
95
|
+
- `default` lets Metabase pick.
|
|
164
96
|
|
|
165
|
-
|
|
166
|
-
| ---------------------------------- | ------------------------------- |
|
|
167
|
-
| `concat` | 2+ expressions |
|
|
168
|
-
| `substring` | str, start (1-indexed), length? |
|
|
169
|
-
| `replace` | str, find, replace |
|
|
170
|
-
| `regex-match-first` | str, regex |
|
|
171
|
-
| `split-part` | str, delimiter, position |
|
|
172
|
-
| `trim` `ltrim` `rtrim` | 1 string |
|
|
173
|
-
| `upper` `lower` | 1 string |
|
|
174
|
-
| `length` | 1 string |
|
|
175
|
-
| `host` `domain` `subdomain` `path` | 1 URL string |
|
|
97
|
+
## Field option: `binning`
|
|
176
98
|
|
|
177
|
-
|
|
99
|
+
On a numeric or coordinate field ref in `breakout`:
|
|
178
100
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
| `today` | none | date |
|
|
183
|
-
| `interval` | amount, unit | a temporal interval |
|
|
184
|
-
| `datetime-add` | temporal, amount, unit | |
|
|
185
|
-
| `datetime-subtract` | temporal, amount, unit | |
|
|
186
|
-
| `datetime-diff` | datetime1, datetime2, unit | |
|
|
187
|
-
| `convert-timezone` | temporal, target-tz, source-tz? | |
|
|
188
|
-
| `get-year` `get-quarter` `get-month` `get-day` `get-hour` `get-minute` `get-second` | 1 temporal | integer component |
|
|
189
|
-
| `get-day-of-week` | temporal, mode? | mode `iso`/`us`/`instance` |
|
|
190
|
-
| `get-week` | temporal, mode? | mode `iso`/`us`/`instance` |
|
|
191
|
-
| `temporal-extract` | temporal, unit, mode? | generic extraction |
|
|
192
|
-
| `month-name` `quarter-name` `day-name` | 1 integer | name from number |
|
|
101
|
+
- `{"strategy": "num-bins", "num-bins": 10}`: equal-width bins.
|
|
102
|
+
- `{"strategy": "bin-width", "bin-width": 5}`: a fixed width.
|
|
103
|
+
- `{"strategy": "default"}`: Metabase picks.
|
|
193
104
|
|
|
194
|
-
|
|
195
|
-
`minute`, `second`, `millisecond`. `datetime-diff` units: same minus `millisecond`.
|
|
196
|
-
`temporal-extract` units: `year-of-era`, `quarter-of-year`, `month-of-year`,
|
|
197
|
-
`week-of-year-iso`, `week-of-year-us`, `week-of-year-instance`, `day-of-month`,
|
|
198
|
-
`day-of-week`, `day-of-week-iso`, `hour-of-day`, `minute-of-hour`, `second-of-minute`.
|
|
105
|
+
## References
|
|
199
106
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
| --------- | ----------------- |
|
|
204
|
-
| `integer` | string or numeric |
|
|
205
|
-
| `float` | string |
|
|
206
|
-
| `text` | 1 expression |
|
|
207
|
-
|
|
208
|
-
### Conditional
|
|
209
|
-
|
|
210
|
-
| Op | Args | Notes |
|
|
211
|
-
| ---------- | ------------------------------ | ---------------------------------------------------- |
|
|
212
|
-
| `case` | `[[cond, value], …]`, default? | if/then/else; default is the trailing positional arg |
|
|
213
|
-
| `if` | same as `case` | alias for `case` |
|
|
214
|
-
| `coalesce` | 2+ expressions | first non-null |
|
|
215
|
-
|
|
216
|
-
```json
|
|
217
|
-
["case", { "lib/expression-name": "Tier" },
|
|
218
|
-
[[[">", {…}, ["field", {…}, 14], 100], "Premium"],
|
|
219
|
-
[["<=", {…}, ["field", {…}, 14], 20], "Budget"]],
|
|
220
|
-
"Standard"]
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
(`case`'s first arg is a list of `[condition, value]` pairs; the optional 4th
|
|
224
|
-
positional arg is the default.)
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## References (within clauses)
|
|
229
|
-
|
|
230
|
-
| Ref | Shape | Notes |
|
|
231
|
-
| ----------- | ------------------------------------ | ------------------------------------------------------------------------------ |
|
|
232
|
-
| field | `["field", {…}, <field-id>]` | numeric id; options may carry `base-type`, `temporal-unit`, `binning` |
|
|
233
|
-
| expression | `["expression", {…}, "<name>"]` | by the expression's `lib/expression-name` string |
|
|
234
|
-
| aggregation | `["aggregation", {…}, "<agg-uuid>"]` | 3rd arg is the **string** `lib/uuid` of the target aggregation, not a position |
|
|
235
|
-
|
|
236
|
-
## Field option: temporal bucketing
|
|
237
|
-
|
|
238
|
-
`temporal-unit` in a field ref's options buckets a datetime.
|
|
239
|
-
|
|
240
|
-
- Truncation: `default`, `millisecond`, `second`, `minute`, `hour`, `day`, `week`,
|
|
241
|
-
`month`, `quarter`, `year`.
|
|
242
|
-
- Extraction (returns an integer): `minute-of-hour`, `hour-of-day`, `day-of-week`,
|
|
243
|
-
`day-of-month`, `day-of-year`, `week-of-year`, `month-of-year`, `quarter-of-year`,
|
|
244
|
-
`year-of-era`, `second-of-minute`. (The `*-iso`/`*-us` variants are `temporal-extract`
|
|
245
|
-
operator modes, not field-option bucketing units.)
|
|
246
|
-
|
|
247
|
-
```json
|
|
248
|
-
["field", { "temporal-unit": "month" }, 22]
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## Field option: binning
|
|
252
|
-
|
|
253
|
-
`binning` in a field ref's options groups a numeric/coordinate column.
|
|
254
|
-
|
|
255
|
-
| `strategy` | Extra property | Notes |
|
|
256
|
-
| ----------- | -------------------- | -------------------------------- |
|
|
257
|
-
| `num-bins` | `num-bins` (integer) | fixed number of equal-width bins |
|
|
258
|
-
| `bin-width` | `bin-width` (number) | fixed bin width |
|
|
259
|
-
| `default` | — | Metabase chooses |
|
|
260
|
-
|
|
261
|
-
```json
|
|
262
|
-
["field", { "binning": { "strategy": "num-bins", "num-bins": 10 } }, 14]
|
|
263
|
-
```
|
|
107
|
+
- field: `["field", {…}, <field id>]`, or `["field", {"base-type": "type/…"}, "<column name>"]` for a previous stage's or a source card's column
|
|
108
|
+
- expression: `["expression", {}, "<expression name>"]`, same stage
|
|
109
|
+
- aggregation: `["aggregation", {}, "<lib/uuid>"]`, the `lib/uuid` (from `mb uuid`) set in the options of an aggregation of the same stage
|
|
@@ -43,7 +43,7 @@ mb field update 1711 --body '{"semantic_type":"type/FK","fk_target_field_id":168
|
|
|
43
43
|
- Queries can pull columns from the related table with no explicit join — `["field", {"source-field": 1711}, 1682]` in MBQL (see `mbql`).
|
|
44
44
|
- Dashboard **linked filters** become possible (a State filter narrowing a City filter). **Linked filters read only these table-metadata FKs** — never a join you wrote inside a saved question — which is why a linked filter that "shows values it shouldn't" almost always means the FK isn't set in metadata. (See `dashboard`.)
|
|
45
45
|
|
|
46
|
-
Removing the `type/FK` semantic type auto-clears `fk_target_field_id`. Point a FK only at a field in the **same database** —
|
|
46
|
+
Removing the `type/FK` semantic type auto-clears `fk_target_field_id`. Point a FK only at a field in the **same database** — a cross-database target is invalid and never resolves to a relationship.
|
|
47
47
|
|
|
48
48
|
## Semantic types are labels, not casts
|
|
49
49
|
|
|
@@ -71,7 +71,13 @@ Everything else on a field/table (physical `name`, `base_type`, `effective_type`
|
|
|
71
71
|
`display_name` · `description` · `caveats` · `points_of_interest` · `semantic_type` · `coercion_strategy` · `fk_target_field_id` · `visibility_type` · `has_field_values` · `settings` · `nfc_path` · `json_unfolding`
|
|
72
72
|
|
|
73
73
|
**`PUT /api/table/:id` (`mb table update`)**
|
|
74
|
-
`display_name` · `description` · `visibility_type` · `field_order` (`database` / `alphabetical` / `custom` / `smart`) · `entity_type` · `caveats` · `points_of_interest` · `show_in_getting_started` · `owner_user_id` / `owner_email` (ownership) · `data_layer` / `data_authority` / `data_source` (data-governance tiers)
|
|
74
|
+
`display_name` · `description` · `visibility_type` · `field_order` (`database` / `alphabetical` / `custom` / `smart`) · `entity_type` · `caveats` · `points_of_interest` · `show_in_getting_started` · `owner_user_id` / `owner_email` (ownership) · `data_layer` / `data_authority` / `data_source` (data-governance tiers)
|
|
75
|
+
|
|
76
|
+
<!-- requires: library -->
|
|
77
|
+
|
|
78
|
+
· `collection_id` — the Library **Data** collection a published table sits in (`mb library publish` sets it; see `core`)
|
|
79
|
+
|
|
80
|
+
<!-- /requires -->
|
|
75
81
|
|
|
76
82
|
## Coercion strategies (common)
|
|
77
83
|
|
|
@@ -8,7 +8,7 @@ allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
|
|
|
8
8
|
|
|
9
9
|
**Prefer a structured query.** Native SQL is a Metabase query whose single stage is raw SQL (`mbql.stage/native`) instead of structured MBQL (`mbql.stage/mbql`) — both are the same query envelope (`mbql`). Reach for a native stage only when a structured query genuinely can't express it — engine-specific functions, CTEs, window logic beyond `offset`, hairy hand-tuned SQL — or when the user asks for SQL. If you can write it as a structured stage, do.
|
|
10
10
|
|
|
11
|
-
General flag conventions, body-input precedence
|
|
11
|
+
General flag conventions, body-input precedence and `./.scratch` live in `core` (`mb skills get core`).
|
|
12
12
|
|
|
13
13
|
## The shape
|
|
14
14
|
|
|
@@ -28,13 +28,13 @@ A native `dataset_query` is a query with one **native stage** — the `lib/type:
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
This is the form a card stores and returns — author it. The CLI **pre-flight-validates** it — the envelope, the template-tag shapes, the field refs — through the usual `--print-schema → --dry-run → run` loop (`mbql`), and a saved card **round-trips** in exactly this shape: `mb card get <id> --full --json`, edit the `stages[0].native` string, send it straight back. Only the
|
|
31
|
+
This is the form a card stores and returns — author it. The CLI **pre-flight-validates** it — the envelope, the template-tag shapes, the field refs — through the usual `--print-schema → --dry-run → run` loop (`mbql`), and a saved card **round-trips** in exactly this shape: `mb card get <id> --full --json`, edit the `stages[0].native` string, send it straight back. Only the warehouse parses the SQL string, so a **SQL** syntax error surfaces when you run it, not at `--dry-run`. A parameterless query needs no `template-tags` — just the `native` string.
|
|
32
32
|
|
|
33
33
|
You may see an older flat form in cards created long ago — `{database, type:"native", native:{query}}`. The server still accepts it (it normalizes to the above) but it skips pre-flight and doesn't round-trip — **don't author it**.
|
|
34
34
|
|
|
35
35
|
## Parameters are template tags
|
|
36
36
|
|
|
37
|
-
Every `{{name}}` in the SQL must have a matching entry in the stage's `template-tags`, keyed by that name. **The three must agree exactly:** the `{{name}}` in SQL = the map key = the entry's `"name"` field. Names are case-sensitive (`{{Cat}}` ≠ `{{cat}}`). A `{{name}}` with no entry fails at run time; an unused entry is ignored.
|
|
37
|
+
Every `{{name}}` in the SQL must have a matching entry in the stage's `template-tags`, keyed by that name. **The three must agree exactly:** the `{{name}}` in SQL = the map key = the entry's `"name"` field. Names are case-sensitive (`{{Cat}}` ≠ `{{cat}}`). A `{{name}}` with no entry fails at run time; an unused entry is ignored. `--dry-run` and a run fail on a raw variable with no value or `default` outside an optional `[[ … ]]` clause, and on any `"required": true` tag with no value; a field filter with no value compiles to `1 = 1` and matches every row.
|
|
38
38
|
|
|
39
39
|
Four kinds of tag, by `type`:
|
|
40
40
|
|
|
@@ -45,7 +45,7 @@ Four kinds of tag, by `type`:
|
|
|
45
45
|
| **Snippet** | `snippet` | `{{snippet: Active Rows}}` | a reusable SQL fragment (`mb snippet`) |
|
|
46
46
|
| **Card reference** | `card` | `{{#42}}` or `{{#42-slug}}` | another saved query, as a subquery |
|
|
47
47
|
|
|
48
|
-
Give each tag an `id
|
|
48
|
+
Give each tag an `id`, unique among the tags; the tag's name serves. Wrap any clause that should be droppable when its value is empty in **`[[ … ]]`**, keyword and all: `[[AND {{status}}]]`, not `AND [[{{status}}]]`. Only one level of nesting; a query using several optional `[[AND …]]` blocks needs a real `WHERE` first (e.g. `WHERE true [[AND {{a}}]] [[AND {{b}}]]`).
|
|
49
49
|
|
|
50
50
|
## The decision that matters: field filter vs. raw variable
|
|
51
51
|
|
|
@@ -62,7 +62,7 @@ Field filters only bind to a **real, connected database column** — not an expr
|
|
|
62
62
|
|
|
63
63
|
```json
|
|
64
64
|
"status": {
|
|
65
|
-
"id": "
|
|
65
|
+
"id": "status",
|
|
66
66
|
"name": "status",
|
|
67
67
|
"display-name": "Status",
|
|
68
68
|
"type": "dimension",
|
|
@@ -71,7 +71,7 @@ Field filters only bind to a **real, connected database column** — not an expr
|
|
|
71
71
|
}
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
**`dimension` is a field ref: `["field", {options}, <field-id>]`** — options object **second**, id **third**, exactly the `mbql` rule.
|
|
74
|
+
**`dimension` is a field ref: `["field", {options}, <field-id>]`** — options object **second**, id **third**, exactly the `mbql` rule. Send `{}` for the options. The field id comes from `table get <id> --include fields`.
|
|
75
75
|
|
|
76
76
|
`widget-type` must suit the column's type and is a closed enum (same vocabulary as dashboard filter `type`): string ops (`string/=`, `string/!=`, `string/contains`, `string/starts-with`, …), number ops (`number/=`, `number/between`, `number/>=`, …), dates (`date/all-options`, `date/range`, `date/relative`, `date/month-year`, …), plus `category`, `id`, `boolean/=`, and the `location/*` set. Text column → a `string/*` or `category`; datetime → a `date/*`; numeric → a `number/*`. `date/all-options` is the most flexible date widget.
|
|
77
77
|
|
|
@@ -79,7 +79,7 @@ Field filters only bind to a **real, connected database column** — not an expr
|
|
|
79
79
|
|
|
80
80
|
```json
|
|
81
81
|
"min_total": {
|
|
82
|
-
"id": "
|
|
82
|
+
"id": "min_total",
|
|
83
83
|
"name": "min_total",
|
|
84
84
|
"display-name": "Minimum total",
|
|
85
85
|
"type": "number",
|
|
@@ -98,7 +98,7 @@ Snippet and card-reference bodies (and the full field list for every kind) are i
|
|
|
98
98
|
|
|
99
99
|
## Wiring, defaults, and running
|
|
100
100
|
|
|
101
|
-
**
|
|
101
|
+
**A tag's default is the tag's own `default`.** Metabase derives the card's `parameters` from the template tags; declare one in the card's `parameters` array (alongside `dataset_query`) only to give it a dropdown source, `values_source_type` (`static-list` / `card`). The declared parameter's `id` is the tag's `id`, and its `target` links back to the tag: `["dimension", ["template-tag", "status"]]` for a field filter, `["variable", ["template-tag", "min_total"]]` for a raw variable.
|
|
102
102
|
|
|
103
103
|
**Run a saved card with values** via `card query`, whose `--parameters` is a JSON array of `{type, target, value}` — same `target` grammar:
|
|
104
104
|
|
|
@@ -111,7 +111,6 @@ mb card query 12 --parameters '[{"type":"string/=","target":["dimension",["templ
|
|
|
111
111
|
## Don't
|
|
112
112
|
|
|
113
113
|
- Don't wrap a field filter in an operator (`WHERE col = {{ff}}`) — write it bare (`WHERE {{ff}}`).
|
|
114
|
-
- Don't write the field-filter `dimension` in the legacy `["field", id, null]` shape — use `["field", {}, id]` (options second).
|
|
115
114
|
- Don't author the flat `{type:"native", …}` form — send the native stage above.
|
|
116
115
|
- Don't use native SQL for DDL or multiple statements — the editor is read-only, single-statement; `CREATE`/`UPDATE`/`;`-chained SQL is unsupported. To materialize a table, use a `transform`.
|
|
117
116
|
- Don't expect `[[ ]]` to save you from a case/type mismatch — `WHERE plan = {{p}}` returns zero rows on a case-sensitive engine if the value's case is off; that's a value problem, not syntax.
|
|
@@ -4,13 +4,13 @@ Every template-tag body, the widget-type vocabulary, and the parameter-object sh
|
|
|
4
4
|
|
|
5
5
|
## Template-tag bodies by `type`
|
|
6
6
|
|
|
7
|
-
The `template-tags` value is a map keyed by tag name; each entry's `name` must equal its key and the `{{name}}` in the SQL. `id` is
|
|
7
|
+
The `template-tags` value is a map keyed by tag name; each entry's `name` must equal its key and the `{{name}}` in the SQL. `id` is any string unique among the tags; the tag's name serves.
|
|
8
8
|
|
|
9
9
|
### Raw variable — `text` / `number` / `date` / `boolean`
|
|
10
10
|
|
|
11
11
|
```json
|
|
12
12
|
"min_total": {
|
|
13
|
-
"id": "
|
|
13
|
+
"id": "min_total",
|
|
14
14
|
"name": "min_total",
|
|
15
15
|
"display-name": "Minimum total",
|
|
16
16
|
"type": "number",
|
|
@@ -24,7 +24,7 @@ The `template-tags` value is a map keyed by tag name; each entry's `name` must e
|
|
|
24
24
|
| `name` | ✓ | equals map key and `{{name}}` |
|
|
25
25
|
| `display-name` | ✓ | label shown in the widget |
|
|
26
26
|
| `type` | ✓ | `text` \| `number` \| `date` \| `boolean` |
|
|
27
|
-
| `id` |
|
|
27
|
+
| `id` | ✓ | unique among the tags; the tag's name |
|
|
28
28
|
| `required` | — | `true` blocks the run until a value is given |
|
|
29
29
|
| `default` | — | value used when none passed (string form) |
|
|
30
30
|
|
|
@@ -34,34 +34,31 @@ SQL: `{{min_total}}`, spliced literally — you write the operator (`total > {{m
|
|
|
34
34
|
|
|
35
35
|
```json
|
|
36
36
|
"status": {
|
|
37
|
-
"id": "
|
|
37
|
+
"id": "status",
|
|
38
38
|
"name": "status",
|
|
39
39
|
"display-name": "Status",
|
|
40
40
|
"type": "dimension",
|
|
41
41
|
"dimension": ["field", {}, 141],
|
|
42
|
-
"widget-type": "string/="
|
|
43
|
-
"default": null,
|
|
44
|
-
"options": null,
|
|
45
|
-
"alias": null
|
|
42
|
+
"widget-type": "string/="
|
|
46
43
|
}
|
|
47
44
|
```
|
|
48
45
|
|
|
49
|
-
| Field | Req | Notes
|
|
50
|
-
| ------------- | --- |
|
|
51
|
-
| `type` | ✓ | `"dimension"`
|
|
52
|
-
| `dimension` | ✓ | field ref `["field", {}, <id>]` — options object second, id third (the `mbql` rule)
|
|
53
|
-
| `widget-type` | ✓ | the widget/operator; must suit the column type (table below)
|
|
54
|
-
| `default` | — | e.g. a value, or a `["2024-01-01","2024-12-31"]` range
|
|
55
|
-
| `options` | — | filter options map (e.g. case sensitivity)
|
|
56
|
-
| `alias` | — | set when the column comes from an aliased table in the SQL
|
|
46
|
+
| Field | Req | Notes |
|
|
47
|
+
| ------------- | --- | ----------------------------------------------------------------------------------- |
|
|
48
|
+
| `type` | ✓ | `"dimension"` |
|
|
49
|
+
| `dimension` | ✓ | field ref `["field", {}, <id>]` — options object second, id third (the `mbql` rule) |
|
|
50
|
+
| `widget-type` | ✓ | the widget/operator; must suit the column type (table below) |
|
|
51
|
+
| `default` | — | e.g. a value, or a `["2024-01-01","2024-12-31"]` range |
|
|
52
|
+
| `options` | — | filter options map (e.g. case sensitivity) |
|
|
53
|
+
| `alias` | — | set when the column comes from an aliased table in the SQL |
|
|
57
54
|
|
|
58
|
-
SQL: bare — `WHERE {{status}}`. Never `WHERE status = {{status}}`.
|
|
55
|
+
SQL: bare — `WHERE {{status}}`. Never `WHERE status = {{status}}`.
|
|
59
56
|
|
|
60
57
|
### Snippet — `snippet`
|
|
61
58
|
|
|
62
59
|
```json
|
|
63
60
|
"snippet: Active Rows": {
|
|
64
|
-
"id": "
|
|
61
|
+
"id": "snippet: Active Rows",
|
|
65
62
|
"name": "snippet: Active Rows",
|
|
66
63
|
"display-name": "Snippet: Active Rows",
|
|
67
64
|
"type": "snippet",
|
|
@@ -76,7 +73,7 @@ SQL: `{{snippet: Active Rows}}`. Create/manage the fragment with `mb snippet` (`
|
|
|
76
73
|
|
|
77
74
|
```json
|
|
78
75
|
"#42": {
|
|
79
|
-
"id": "
|
|
76
|
+
"id": "#42",
|
|
80
77
|
"name": "#42",
|
|
81
78
|
"display-name": "#42",
|
|
82
79
|
"type": "card",
|
|
@@ -86,13 +83,17 @@ SQL: `{{snippet: Active Rows}}`. Create/manage the fragment with `mb snippet` (`
|
|
|
86
83
|
|
|
87
84
|
SQL: `{{#42}}` or `{{#42-slug}}`, used where a table/subquery goes (`FROM {{#42}}`, `WITH x AS {{#42}}`). Runs with the referenced card's own defaults; no user value.
|
|
88
85
|
|
|
89
|
-
|
|
86
|
+
<!-- requires: nativeTableTemplateTag -->
|
|
90
87
|
|
|
91
|
-
|
|
88
|
+
### Source table — `table`
|
|
89
|
+
|
|
90
|
+
A niche type that references a warehouse table by id (`{type: "table", table-id: <id>}`, optional `source-filters`) where a table/subquery goes — analogous to a card reference but pointing at a raw table. Reach for a card reference (`card`) unless you specifically need a bare-table source tag.
|
|
91
|
+
|
|
92
|
+
<!-- /requires -->
|
|
92
93
|
|
|
93
94
|
### Temporal unit — `temporal-unit`
|
|
94
95
|
|
|
95
|
-
A widget that lets the viewer pick the time bucket (day/week/month/…) for a datetime column. Body mirrors a field filter (`dimension`
|
|
96
|
+
A widget that lets the viewer pick the time bucket (day/week/month/…) for a datetime column. Body mirrors a field filter (`dimension` field ref, optional `alias`) with `type: "temporal-unit"`.
|
|
96
97
|
|
|
97
98
|
## `widget-type` by column type
|
|
98
99
|
|
|
@@ -113,16 +114,15 @@ Closed enum — same vocabulary as a dashboard parameter `type`. Pick one whose
|
|
|
113
114
|
|
|
114
115
|
Same object, two contexts. `target` links the parameter to a template tag: `["dimension", ["template-tag", "<name>"]]` for a field filter, `["variable", ["template-tag", "<name>"]]` for a raw variable.
|
|
115
116
|
|
|
116
|
-
**Declared** — in the card's `parameters` array, to set a default
|
|
117
|
+
**Declared** — in the card's `parameters` array, to set a dropdown source. Its `id` is the tag's `id`; the default is the tag's `default`:
|
|
117
118
|
|
|
118
119
|
```json
|
|
119
120
|
{
|
|
120
|
-
"id": "
|
|
121
|
+
"id": "status",
|
|
121
122
|
"name": "status",
|
|
122
123
|
"slug": "status",
|
|
123
124
|
"type": "string/=",
|
|
124
125
|
"target": ["dimension", ["template-tag", "status"]],
|
|
125
|
-
"default": "active",
|
|
126
126
|
"values_source_type": "static-list",
|
|
127
127
|
"values_source_config": { "values": ["active", "churned", "trial"] }
|
|
128
128
|
}
|
|
@@ -156,14 +156,14 @@ What `mb card create --file` consumes:
|
|
|
156
156
|
"native": "SELECT status, count(*) FROM orders WHERE total > {{min_total}} [[AND {{status}}]] GROUP BY status",
|
|
157
157
|
"template-tags": {
|
|
158
158
|
"min_total": {
|
|
159
|
-
"id": "
|
|
159
|
+
"id": "min_total",
|
|
160
160
|
"name": "min_total",
|
|
161
161
|
"display-name": "Minimum total",
|
|
162
162
|
"type": "number",
|
|
163
163
|
"default": "0"
|
|
164
164
|
},
|
|
165
165
|
"status": {
|
|
166
|
-
"id": "
|
|
166
|
+
"id": "status",
|
|
167
167
|
"name": "status",
|
|
168
168
|
"display-name": "Status",
|
|
169
169
|
"type": "dimension",
|
|
@@ -110,7 +110,13 @@ An alert body has exactly three parts:
|
|
|
110
110
|
|
|
111
111
|
Recipients are `{"email": "a@b.com"}` for an external address or `{"id": <user-id>}` for a Metabase user. A Slack channel is **not** a recipient — it goes in `details`: `{"channel_type": "slack", "details": {"channel": "#general"}, …}`.
|
|
112
112
|
|
|
113
|
-
**`skip_if_empty: true`** suppresses the send when the dashboard's questions return no rows — the way to build a "only tell me when something happened" dashboard report.
|
|
113
|
+
**`skip_if_empty: true`** suppresses the send when the dashboard's questions return no rows — the way to build a "only tell me when something happened" dashboard report.
|
|
114
|
+
|
|
115
|
+
<!-- requires: dashboardSubscriptionFilters -->
|
|
116
|
+
|
|
117
|
+
**`parameters`** sets filter values for this subscription only, so one dashboard can feed several audiences a different slice. Its entries are dashboard parameter values — the parameter `id`s come from `mb dashboard get <id> --fields parameters --json` (see the `dashboard` skill).
|
|
118
|
+
|
|
119
|
+
<!-- /requires -->
|
|
114
120
|
|
|
115
121
|
`mb subscription list --archived` is a **swap, not a union** — it returns archived subscriptions _instead of_ active ones, never both. `mb dashboard subscriptions <id>` is the list scoped to one dashboard. `mb subscription archive <id>` also disables every channel on it, so restoring takes two steps: `update --body '{"archived":false}'`, then re-send the `channels` array with `enabled: true`.
|
|
116
122
|
|