diff --git a/frontend/src/metabase/components/SaveQuestionModal.jsx b/frontend/src/metabase/components/SaveQuestionModal.jsx index adcca466084d6215bd827a8b412ecd8ab4f9e80b..4c4a015cb8bb4469d348e6915221b3a1a0410b2a 100644 --- a/frontend/src/metabase/components/SaveQuestionModal.jsx +++ b/frontend/src/metabase/components/SaveQuestionModal.jsx @@ -145,7 +145,7 @@ export default class SaveQuestionModal extends Component { onChange={(value) => this.onChange("saveType", value)} options={[ { name: `Replace original question, "${this.props.originalCard.name}"`, value: "overwrite" }, - { name: "Save as new question", value: "replace" }, + { name: "Save as new question", value: "create" }, ]} isVertical /> diff --git a/frontend/src/metabase/query_builder/components/AggregationWidget.jsx b/frontend/src/metabase/query_builder/components/AggregationWidget.jsx index 31ed5e5c09c7b7426f6d310b44003299db7581bb..80e3e1d671fb63a256f44a4712b5173f117dfaa0 100644 --- a/frontend/src/metabase/query_builder/components/AggregationWidget.jsx +++ b/frontend/src/metabase/query_builder/components/AggregationWidget.jsx @@ -27,7 +27,7 @@ export default class AggregationWidget extends Component { } static propTypes = { - aggregation: PropTypes.array.isRequired, + aggregation: PropTypes.array, tableMetadata: PropTypes.object.isRequired, customFields: PropTypes.object, updateAggregation: PropTypes.func.isRequired, @@ -51,7 +51,7 @@ export default class AggregationWidget extends Component { const fieldId = AggregationClause.getField(aggregation); let selectedAggregation = getAggregator(AggregationClause.getOperator(aggregation)); - if (!_.findWhere(tableMetadata.aggregation_options, { short: selectedAggregation.short })) { + if (selectedAggregation && !_.findWhere(tableMetadata.aggregation_options, { short: selectedAggregation.short })) { // if this table doesn't support the selected aggregation, prompt the user to select a different one selectedAggregation = null; } diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx index b97632aa76b31575b791ce0c239e02fa71f49c8e..6171e7022b4997d193e02864ac563e5105932f0b 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker.jsx @@ -105,7 +105,7 @@ const OPERATORS = [ }, { name: "Between", - init: (filter) => ["BETWEEN", filter[1], null, null], + init: (filter) => ["BETWEEN", filter[1], getDate(filter[2]), getDate(filter[3])], test: ([op]) => op === "BETWEEN", widget: MultiDatePicker, }, diff --git a/project.clj b/project.clj index a3aeb88bfab40ee54b4123b497e42118215a471b..7fc9ee5432f44fb082dd77c8d613ef311daa2fb6 100644 --- a/project.clj +++ b/project.clj @@ -44,7 +44,7 @@ "v3-rev135-1.22.0"] [com.google.apis/google-api-services-bigquery ; Google BigQuery Java Client Library "v2-rev324-1.22.0"] - [com.h2database/h2 "1.4.192"] ; embedded SQL database + [com.h2database/h2 "1.4.193"] ; embedded SQL database [com.mattbertolini/liquibase-slf4j "2.0.0"] ; Java Migrations lib [com.mchange/c3p0 "0.9.5.2"] ; connection pooling library [com.novemberain/monger "3.1.0"] ; MongoDB Driver diff --git a/src/metabase/driver/mongo.clj b/src/metabase/driver/mongo.clj index addce073530d27f4a23e4bb9f0291e937a87fe2d..6ebee0cef2d8340681fd80d1139fc3bc96dcadaf 100644 --- a/src/metabase/driver/mongo.clj +++ b/src/metabase/driver/mongo.clj @@ -192,6 +192,9 @@ :display-name "Database password" :type :password :placeholder "******"} + {:name "authdb" + :display-name "Authentication Database" + :placeholder "Optional database to use when authenticating"} {:name "ssl" :display-name "Use a secure connection (SSL)?" :type :boolean diff --git a/src/metabase/driver/mongo/util.clj b/src/metabase/driver/mongo/util.clj index b4dfcb5b5836c853c792124f7cf3bb303e8763d9..52e93eb088a8ac62476bae4d5fe998e8b6a0ea44 100644 --- a/src/metabase/driver/mongo/util.clj +++ b/src/metabase/driver/mongo/util.clj @@ -43,7 +43,7 @@ "Run F with a new connection (bound to `*mongo-connection*`) to DATABASE. Don't use this directly; use `with-mongo-connection`." [f database] - (let [{:keys [dbname host port user pass ssl] + (let [{:keys [dbname host port user pass ssl authdb] :or {port 27017, pass "", ssl false}} (cond (string? database) {:dbname database} (:dbname (:details database)) (:details database) ; entire Database obj @@ -53,9 +53,12 @@ user) pass (when (seq pass) pass) + authdb (if (seq authdb) + authdb + dbname) server-address (mg/server-address host port) credentials (when user - (mcred/create user dbname pass)) + (mcred/create user authdb pass)) connect (partial mg/connect server-address (build-connection-options :ssl? ssl)) conn (if credentials (connect credentials) diff --git a/src/metabase/query_processor/expand.clj b/src/metabase/query_processor/expand.clj index 2ad8ad88d633ad97846c05f86e9e34454432da32..11dcaf31528bb4434baa8e33b7db953014fe8b45 100644 --- a/src/metabase/query_processor/expand.clj +++ b/src/metabase/query_processor/expand.clj @@ -51,7 +51,7 @@ [id :- su/IntGreaterThanZero] (i/map->FieldPlaceholder {:field-id id})) -(s/defn ^:private ^:always-validate field :- i/AnyField +(s/defn ^:private ^:always-validate field :- i/AnyFieldOrExpression "Generic reference to a `Field`. F can be an integer Field ID, or various other forms like `fk->` or `aggregation`." [f] (if (integer? f) @@ -116,7 +116,13 @@ (defn- field-or-expression [f] (if (instance? Expression f) - (update f :args (partial map field-or-expression)) ; recursively call field-or-expression on all the args of the expression + ;; recursively call field-or-expression on all the args inside the expression unless they're numbers + ;; plain numbers are always assumed to be numeric literals here; you must use MBQL '98 `:field-id` syntax to refer to Fields inside an expression <3 + (update f :args #(for [arg %] + (if (number? arg) + arg + (field-or-expression arg)))) + ;; otherwise if it's not an Expression it's a a (field f))) (s/defn ^:private ^:always-validate ag-with-field :- i/Aggregation [ag-type f] diff --git a/src/metabase/query_processor/interface.clj b/src/metabase/query_processor/interface.clj index e4d6010e22b282656f150548dbccc44dcd9900f7..0e95c8e4e8fb027ea8c0ab33ee01f03ee896a048 100644 --- a/src/metabase/query_processor/interface.clj +++ b/src/metabase/query_processor/interface.clj @@ -185,10 +185,10 @@ args :- [(s/cond-pre (s/recursive #'RValue) (s/recursive #'Aggregation))]]) -(def AnyField +(def AnyFieldOrExpression "Schema for a `FieldPlaceholder`, `AgRef`, or `Expression`." (s/named (s/cond-pre ExpressionRef Expression FieldPlaceholderOrAgRef) - "Valid field, ag field reference, or expression reference.")) + "Valid field, ag field reference, expression, or expression reference.")) (def LiteralDatetimeString @@ -302,7 +302,7 @@ (def OrderBy "Schema for top-level `order-by` clause in an MBQL query." - (s/named {:field AnyField + (s/named {:field AnyFieldOrExpression :direction OrderByDirection} "Valid order-by subclause")) @@ -317,7 +317,7 @@ "Schema for an MBQL query." {(s/optional-key :aggregation) [Aggregation] (s/optional-key :breakout) [FieldPlaceholderOrExpressionRef] - (s/optional-key :fields) [AnyField] + (s/optional-key :fields) [AnyFieldOrExpression] (s/optional-key :filter) Filter (s/optional-key :limit) su/IntGreaterThanZero (s/optional-key :order-by) [OrderBy] diff --git a/test/metabase/driver/druid_test.clj b/test/metabase/driver/druid_test.clj index b343ca447ad16e7499ed07e8957187b09aa05c05..3cb08f21eb73411193c1aa1ecb05a10dea137b13 100644 --- a/test/metabase/driver/druid_test.clj +++ b/test/metabase/driver/druid_test.clj @@ -192,3 +192,13 @@ (druid-query-returning-rows (ql/aggregation (ql/+ 1 (ql/count))) (ql/breakout $venue_price))) + +;; aggregation with math inside the aggregation :scream_cat: +(expect-with-engine :druid + [["1" 442.0] + ["2" 1845.0] + ["3" 460.0] + ["4" 245.0]] + (druid-query-returning-rows + (ql/aggregation (ql/sum (ql/+ $venue_price 1))) + (ql/breakout $venue_price))) diff --git a/test/metabase/query_processor_test/expression_aggregations_test.clj b/test/metabase/query_processor_test/expression_aggregations_test.clj index 533e5c606ccb749c263d6e091edd1b47a2de0c30..b0e855f6735b0e9d187505d08cef8ac25e189715 100644 --- a/test/metabase/query_processor_test/expression_aggregations_test.clj +++ b/test/metabase/query_processor_test/expression_aggregations_test.clj @@ -145,3 +145,14 @@ (rows (data/run-query venues (ql/aggregation (ql/+ 1 (ql/count))) (ql/breakout $price))))) + +;; aggregation with math inside the aggregation :scream_cat: +(datasets/expect-with-engines (engines-that-support :expression-aggregations) + [[1 44] + [2 177] + [3 52] + [4 30]] + (format-rows-by [int int] + (rows (data/run-query venues + (ql/aggregation (ql/sum (ql/+ $price 1))) + (ql/breakout $price)))))