{"record":{"id":"b4fed0dd6a47cd67","repo":"cube-js/cube","slug":"date-bin-function-required-for-custom-time-dimens","errorCode":null,"errorMessage":"Date bin function, required for custom time dimension granularities, is not implemented for this data source","messagePattern":"Date bin function, required for custom time dimension granularities, is not implemented for this data source","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/adapter/BaseQuery.js","lineNumber":4158,"sourceCode":"   * @param {string} dimension\n   * @return {string}\n   */\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  timeGroupedColumn(granularity, dimension) {\n    throw new Error('Not implemented');\n  }\n\n  /**\n   * Returns sql for source expression floored to timestamps aligned with\n   * intervals relative to origin timestamp point\n   * @param {string} interval (a value expression of type interval)\n   * @param {string} source (a value expression of type timestamp/date)\n   * @param {string} origin (a value expression of type timestamp/date without timezone)\n   * @returns {string}\n   */\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  dateBin(interval, source, origin) {\n    throw new Error('Date bin function, required for custom time dimension granularities, is not implemented for this data source');\n    // Different syntax possible in different DBs\n  }\n\n  /**\n   * Returns the lowest time unit for the interval\n   * @protected\n   * @param {string} interval\n   * @returns {string}\n   */\n  diffTimeUnitForInterval(interval) {\n    if (/second/i.test(interval)) {\n      return 'second';\n    } else if (/minute/i.test(interval)) {\n      return 'minute';\n    } else if (/hour/i.test(interval)) {\n      return 'hour';\n    } else if (/day/i.test(interval)) {\n      return 'day';","sourceCodeStart":4140,"sourceCodeEnd":4176,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js#L4140-L4176","documentation":"dateBin(interval, source, origin) implements the SQL needed to bin timestamps into custom-granularity intervals aligned to an origin (like Postgres 14's date_bin). BaseQuery's default throws because each DB has different syntax and many have no equivalent. It is only needed when using custom granularities (arbitrary intervals beyond standard day/week/month).","triggerScenarios":"A query uses a custom granularity (e.g. interval like '15 minutes' or non-standard offsets) on a data source whose adapter did not implement dateBin.","commonSituations":"Custom rolling granularities on MySQL/MSSQL/older Postgres without date_bin; migrating queries with custom granularities from Postgres to another DB.","solutions":["Implement dateBin in your adapter (e.g. emulate with epoch math: floor((ts - origin)/interval)*interval + origin)","Restrict the query to standard granularities supported natively by the DB","Upgrade to a data source with native date_bin/binning support"],"exampleFix":"// before\nclass MyQuery extends BaseQuery {} // custom granularity on query\n// after\nclass MyQuery extends BaseQuery {\n  dateBin(interval, source, origin) {\n    return `to_timestamp(floor(extract(epoch from ${source} - ${origin}) / extract(epoch from ${interval})) * extract(epoch from ${interval}) + extract(epoch from ${origin}))`;\n  }\n}","handlingStrategy":"fallback","validationCode":"const standardGranularities = ['second','minute','hour','day','week','month','quarter','year'];\nif (query.timeDimensions?.some(td => td.granularity && !standardGranularities.includes(td.granularity)) &&\n    !adapterImplementsDateBin(dataSource)) {\n  throw new Error(`Custom granularities unsupported on ${dataSource}; use a standard granularity`);\n}","typeGuard":"function supportsDateBin(adapter) {\n  return typeof adapter.dateBin === 'function' &&\n    adapter.dateBin !== BaseQuery.prototype.dateBin;\n}","tryCatchPattern":"try { return await cube.load(query); } catch (e) {\n  if (/Date bin function/.test(e.message)) {\n    return await cube.load({ ...query, timeDimensions: query.timeDimensions.map(td => ({ ...td, granularity: 'day' })) });\n  }\n  throw e;\n}","preventionTips":["Reserve custom granularities for Postgres 14+/ClickHouse/BigQuery","Gate custom granularity usage behind a capability check per data source","Implement dateBin via epoch arithmetic in adapters without native date_bin"],"tags":["schema-compiler","date-bin","custom-granularity","unsupported-feature"],"backgroundTag":"date-bin-not-implemented","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}