Skip to content

Error: too many arguments on function JSON_OBJECT - πŸ› Bug Report β€” Runtime APIsΒ #2412

@lifeiscontent

Description

@lifeiscontent

trying to run the following with D1

produces the following error:

[cause]: Error: too many arguments on function JSON_OBJECT at offset 2909
      at D1Database._sendOrThrow (cloudflare-internal:d1-api:67:24)
      at async D1PreparedStatement.first (cloudflare-internal:d1-api:159:35) {
    [cause]: undefined
WITH RecipeBase AS (
	SELECT
		r.id,
		r.name,
		r.date_published,
		r.description,
		r.recipe_cuisine,
		r.prep_time,
		r.cook_time,
		r.total_time,
		r.recipe_yield,
		r.recipe_category,
		u.name AS author_name,
		n.calories
	FROM
		recipes r
		LEFT JOIN users u ON r.author_id = u.id
		LEFT JOIN nutrition_information n ON r.nutrition_id = n.id
	WHERE
		r.id = 1
),
RecipeImages AS (
	SELECT
		ri.recipe_id,
		JSON_GROUP_ARRAY(ri.image_url) AS images
	FROM
		recipe_images ri
	WHERE
		ri.recipe_id = 1
	GROUP BY
		ri.recipe_id
),
RecipeKeywords AS (
	SELECT
		rk.recipe_id,
		JSON_GROUP_ARRAY(k.keyword) AS keywords
	FROM
		recipe_keywords rk
		JOIN keywords k ON rk.keyword_id = k.id
	WHERE
		rk.recipe_id = 1
	GROUP BY
		rk.recipe_id
),
RecipeIngredients AS (
	SELECT
		ri.recipe_id,
		JSON_GROUP_ARRAY(ri.ingredient) AS ingredients
	FROM
		recipe_ingredients ri
	WHERE
		ri.recipe_id = 1
	GROUP BY
		ri.recipe_id
),
HowToSteps AS (
	SELECT
		ss.recipe_instruction_section_id,
		JSON_GROUP_ARRAY(
			JSON_OBJECT(
				'@type', 'HowToStep', 'name', st.name,
				'text', st.text, 'image', st.image
			)
		) AS steps
	FROM
		recipe_instruction_section_steps ss
		JOIN recipe_instruction_steps st ON ss.recipe_instruction_step_id = st.id
	GROUP BY
		ss.recipe_instruction_section_id
),
RecipeInstructions AS (
	SELECT
		ri.recipe_id,
		JSON_GROUP_ARRAY(
			CASE WHEN ri.instruction_type = 'text' THEN ri.text WHEN ri.instruction_type = 'recipe_instruction_step' THEN JSON_OBJECT(
				'@type', 'HowToStep', 'name', s.name,
				'text', s.text, 'image', s.image
			) WHEN ri.instruction_type = 'recipe_instruction_section' THEN JSON_OBJECT(
				'@type',
				'HowToSection',
				'name',
				sec.name,
				'itemListElement',
				COALESCE(
					hts.steps,
					JSON_ARRAY()
				)
			) END
		) AS instructions
	FROM
		recipe_instructions ri
		LEFT JOIN recipe_instruction_steps s ON ri.instruction_id = s.id
		LEFT JOIN recipe_instruction_sections sec ON ri.instruction_id = sec.id
		LEFT JOIN HowToSteps hts ON sec.id = hts.recipe_instruction_section_id
	WHERE
		ri.recipe_id = 1
	GROUP BY
		ri.recipe_id
),
AggregateRatings AS (
	SELECT
		rr.recipe_id,
		AVG(rr.rating_value) AS rating_value,
		COUNT(rr.rating_value) AS rating_count
	FROM
		recipe_ratings rr
	WHERE
		rr.recipe_id = 1
	GROUP BY
		rr.recipe_id
)
SELECT
	JSON_OBJECT(
		'@context',
		'https://schema.org/',
		'@type',
		'Recipe',
		'name',
		rb.name,
		'image',
		COALESCE(
			RecipeImages.images,
			JSON_ARRAY()
		),
		'author',
		CASE WHEN rb.author_name IS NOT NULL THEN JSON_OBJECT(
			'@type', 'Person', 'name', rb.author_name
		) ELSE NULL END,
		'datePublished',
		rb.date_published,
		'description',
		rb.description,
		'recipeCuisine',
		rb.recipe_cuisine,
		'prepTime',
		rb.prep_time,
		'cookTime',
		rb.cook_time,
		'totalTime',
		rb.total_time,
		'keywords',
		COALESCE(
			RecipeKeywords.keywords,
			JSON_ARRAY()
		),
		'recipeYield',
		rb.recipe_yield,
		'recipeCategory',
		rb.recipe_category,
		'nutrition',
		CASE WHEN rb.calories IS NOT NULL THEN JSON_OBJECT(
			'@type', 'NutritionInformation',
			'calories', rb.calories
		) ELSE NULL END,
		'aggregateRating',
		CASE WHEN ar.rating_value IS NOT NULL THEN JSON_OBJECT(
			'@type', 'AggregateRating', 'ratingValue',
			ar.rating_value, 'ratingCount',
			ar.rating_count
		) ELSE NULL END,
		'recipeIngredient',
		COALESCE(
			RecipeIngredients.ingredients,
			JSON_ARRAY()
		),
		'recipeInstructions',
		COALESCE(
			JSON(
				RecipeInstructions.instructions
			),
			JSON_ARRAY()
		)
	) AS recipe
FROM
	RecipeBase rb
	LEFT JOIN RecipeImages ON rb.id = RecipeImages.recipe_id
	LEFT JOIN RecipeKeywords ON rb.id = RecipeKeywords.recipe_id
	LEFT JOIN RecipeIngredients ON rb.id = RecipeIngredients.recipe_id
	LEFT JOIN RecipeInstructions ON rb.id = RecipeInstructions.recipe_id
	LEFT JOIN AggregateRatings ar ON rb.id = ar.recipe_id;

here's the schema:

-- Table to store users
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL);

-- Table to store nutrition information
CREATE TABLE nutrition_information (id INTEGER PRIMARY KEY, calories TEXT NOT NULL);

-- Table to store individual ratings
CREATE TABLE recipe_ratings (
  id INTEGER PRIMARY KEY,
  recipe_id INTEGER,
  user_id INTEGER,
  rating_value INTEGER NOT NULL,
  FOREIGN KEY (recipe_id) REFERENCES recipes (id),
  FOREIGN KEY (user_id) REFERENCES users (id)
);

-- Table to store recipe instruction steps
CREATE TABLE recipe_instruction_steps (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  text TEXT NOT NULL,
  image TEXT NOT NULL
);

-- Table to store recipe instruction sections
CREATE TABLE recipe_instruction_sections (id INTEGER PRIMARY KEY, name TEXT NOT NULL);

-- Junction table for recipe instruction sections and steps (many-to-many relationship)
CREATE TABLE recipe_instruction_section_steps (
  recipe_instruction_section_id INTEGER,
  recipe_instruction_step_id INTEGER,
  FOREIGN KEY (recipe_instruction_section_id) REFERENCES recipe_instruction_sections (id),
  FOREIGN KEY (recipe_instruction_step_id) REFERENCES recipe_instruction_steps (id),
  PRIMARY KEY (
    recipe_instruction_section_id,
    recipe_instruction_step_id
  )
);

-- Table to store recipes
CREATE TABLE recipes (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  date_published TEXT NOT NULL,
  description TEXT NOT NULL,
  recipe_cuisine TEXT NOT NULL,
  prep_time TEXT NOT NULL,
  cook_time TEXT NOT NULL,
  total_time TEXT NOT NULL,
  recipe_yield TEXT NOT NULL,
  recipe_category TEXT NOT NULL,
  author_id INTEGER,
  nutrition_id INTEGER,
  FOREIGN KEY (author_id) REFERENCES users (id),
  FOREIGN KEY (nutrition_id) REFERENCES nutrition_information (id)
);

-- Table to store recipe images (one-to-many relationship)
CREATE TABLE recipe_images (
  id INTEGER PRIMARY KEY,
  recipe_id INTEGER,
  image_url TEXT NOT NULL,
  FOREIGN KEY (recipe_id) REFERENCES recipes (id)
);

-- Table to store keywords
CREATE TABLE keywords (id INTEGER PRIMARY KEY, keyword TEXT NOT NULL);

-- Junction table to link recipes to keywords (many-to-many relationship)
CREATE TABLE recipe_keywords (
  recipe_id INTEGER,
  keyword_id INTEGER,
  FOREIGN KEY (recipe_id) REFERENCES recipes (id),
  FOREIGN KEY (keyword_id) REFERENCES keywords (id),
  PRIMARY KEY (recipe_id, keyword_id)
);

-- Table to store recipe ingredients (one-to-many relationship)
CREATE TABLE recipe_ingredients (
  id INTEGER PRIMARY KEY,
  recipe_id INTEGER,
  ingredient TEXT NOT NULL,
  FOREIGN KEY (recipe_id) REFERENCES recipes (id)
);

-- Table to store recipe instructions (one-to-many relationship)
CREATE TABLE recipe_instructions (
  id INTEGER PRIMARY KEY,
  recipe_id INTEGER,
  instruction_type TEXT NOT NULL,
  instruction_id INTEGER,
  text TEXT,
  FOREIGN KEY (recipe_id) REFERENCES recipes (id)
);

-- Insert sample data into related tables first
INSERT INTO
  users (id, name)
VALUES
  (1, 'John Doe');

INSERT INTO
  nutrition_information (id, calories)
VALUES
  (1, '200 calories');

INSERT INTO
  recipes (
    id,
    name,
    date_published,
    description,
    recipe_cuisine,
    prep_time,
    cook_time,
    total_time,
    recipe_yield,
    recipe_category,
    author_id,
    nutrition_id
  )
VALUES
  (
    1,
    'Sample Recipe',
    '2024-07-18',
    'A delicious sample recipe.',
    'International',
    'PT20M',
    'PT30M',
    'PT50M',
    '4 servings',
    'Dessert',
    1,
    1
  );

INSERT INTO
  recipe_instruction_steps (id, name, text, image)
VALUES
  (1, 'Step 1', 'Mix ingredients.', 'image1.jpg');

INSERT INTO
  recipe_instruction_sections (id, name)
VALUES
  (1, 'Section 1');

-- Insert records into recipe_instructions
INSERT INTO
  recipe_instructions (recipe_id, instruction_type, instruction_id, text)
VALUES
  (1, 'text', NULL, 'Preheat oven to 350 degrees.'),
  (1, 'recipe_instruction_step', 1, NULL),
  (1, 'recipe_instruction_section', 1, NULL);

-- Insert sample rating
INSERT INTO
  recipe_ratings (recipe_id, user_id, rating_value)
VALUES
  (1, 1, 5);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions