diff --git a/tools/packaging/catalog/catalog-remote.js b/tools/packaging/catalog/catalog-remote.js index c6a242f9c3..41c1bad686 100644 --- a/tools/packaging/catalog/catalog-remote.js +++ b/tools/packaging/catalog/catalog-remote.js @@ -536,14 +536,11 @@ _.extend(RemoteCatalog.prototype, { self.db = null; }, - getVersion: function (name, version) { + getVersion: function (packageName, version) { var result = this._contentQuery( "SELECT content FROM versions WHERE packageName=? AND version=?", - [name, version]); - if(!result || result.length === 0) { - return null; - } - return result[0]; + [packageName, version]); + return filterExactRows(result, { packageName, version }); }, // As getVersion, but returns info on the latest version of the @@ -658,9 +655,7 @@ _.extend(RemoteCatalog.prototype, { var self = this; var result = self._contentQuery( "SELECT content FROM releaseTracks WHERE name=?", name); - if (!result || result.length === 0) - return null; - return result[0]; + return filterExactRows(result, { name }); }, getReleaseVersion: function (track, version) { @@ -668,9 +663,7 @@ _.extend(RemoteCatalog.prototype, { var result = self._contentQuery( "SELECT content FROM releaseVersions WHERE track=? AND version=?", [track, version]); - if (!result || result.length === 0) - return null; - return result[0]; + return filterExactRows(result, { track, version }); }, // Used by make-bootstrap-tarballs. Only should be used on catalogs that are @@ -996,6 +989,29 @@ _.extend(RemoteCatalog.prototype, { } }); +// SQLite has a bizarre philosophy about automaticaly converting between +// different data types, such as strings and floating point numbers: +// https://www.sqlite.org/quirks.html#flexible_typing +// +// This means querying for the string "1.10" in a given column can return +// rows where the column is actually the string "1.1", since SQLite thinks +// you might be talking about the number 1.1 rather than the string you +// actually requested. +// +// This "feature" first became a problem for Meteor after we published +// Meteor 1.10, which caused SQLite to return multiple rows for the +// getReleaseVersion query, including both 1.10 and 1.1.1 (ancient). +// +// While this policy seems completely indefensible, the SQLite project +// does not consider it a bug, which forces us to work around it by +// double-checking the queried results with this helper function: +function filterExactRows(rows, requirements) { + const keys = Object.keys(requirements); + return rows && rows.filter(row => { + return keys.every(key => row[key] === requirements[key]); + })[0] || null; +} + exports.RemoteCatalog = RemoteCatalog; // We put this constant here because we don't have any better place that would otherwise cause a cycle