diff --git a/bin/generate-docs.js b/bin/generate-docs.js index 560828d57..c9bc2578a 100644 --- a/bin/generate-docs.js +++ b/bin/generate-docs.js @@ -207,8 +207,9 @@ function createDeleteExample(serviceName, resourceName, resourceData, thisSchema ${sqlCodeBlockStart} /*+ delete */ DELETE FROM ${providerName}.${serviceName}.${resourceName} -WHERE Identifier = '${resourceData['x-identifiers'].map(id => `{{ ${toSnakeCase(fixCamelCaseIssues(id))} }}`).join('|')}' -AND region = 'us-east-1'; +WHERE + Identifier = '${resourceData['x-identifiers'].map(id => `{{ ${toSnakeCase(fixCamelCaseIssues(id))} }}`).join('|')}' AND + region = 'us-east-1'; ${codeBlockEnd} `; } @@ -242,8 +243,9 @@ UPDATE ${providerName}.${serviceName}.${resourceName} SET PatchDocument = string('{{ { ${patchFields} } | generate_patch_document }}') -WHERE region = '{{ region }}' -AND Identifier = '${identifierValues}'; +WHERE + region = '{{ region }}' AND + Identifier = '${identifierValues}'; ${codeBlockEnd} `; } @@ -401,12 +403,12 @@ Use the following StackQL query and manifest file to create a new ${plural ${sqlCodeBlockStart} /*+ create */ INSERT INTO ${providerName}.${serviceName}.${resourceName} ( - ${requiredKeys.join(",\n ")}, - region + ${requiredKeys.join(",\n ")}, + region ) SELECT -'{{ ${requiredSnakeKeys.join(" }}',\n '{{ ")} }}', -'{{ region }}'; + '{{ ${requiredSnakeKeys.join(" }}',\n '{{ ")} }}', + '{{ region }}'; ${codeBlockEnd} @@ -414,12 +416,12 @@ ${codeBlockEnd} ${sqlCodeBlockStart} /*+ create */ INSERT INTO ${providerName}.${serviceName}.${resourceName} ( - ${allKeys.join(",\n ")}, - region + ${allKeys.join(",\n ")}, + region ) SELECT - '{{ ${allSnakeKeys.join(" }}',\n '{{ ")} }}', - '{{ region }}'; + '{{ ${allSnakeKeys.join(" }}',\n '{{ ")} }}', + '{{ region }}'; ${codeBlockEnd} @@ -580,7 +582,7 @@ function createResourceIndexContent(serviceName, resourceName, resourceType, res }); hasList = true; - sqlExampleListWhere = `${sqlExampleWhere};`; + sqlExampleListWhere = `WHERE\n ${sqlExampleWhere.replace(/^WHERE\s+/, '')};`; } @@ -672,8 +674,8 @@ ${tabItems} const identifierValues = resourceIdentifiers.map(id => `{{ ${toSnakeCase(fixCamelCaseIssues(id))} }}`).join('|'); const identifierClause = `Identifier = '${identifierValues}'`; - sqlExampleListWhere = `${sqlExampleWhere};`; - sqlExampleGetWhere = `${sqlExampleWhere} AND ${identifierClause};`; + sqlExampleListWhere = `WHERE\n ${sqlExampleWhere.replace(/^WHERE\s+/, '')};`; + sqlExampleGetWhere = `WHERE\n ${sqlExampleWhere.replace(/^WHERE\s+/, '')} AND\n ${identifierClause};`; } @@ -1092,33 +1094,33 @@ function generateSchemaJsonForResource(serviceName, resourceName, resourceType, // } function getColumns(properties, isList, isCustom = false, is_tags = false){ - let columns = 'region,'; + let columns = ' region,'; if (isList) { if(Array.isArray(properties)){ properties.forEach(propName => { if(isCustom){ - columns += `\n${propName},`; + columns += `\n ${propName},`; } else { - columns += `\n${toSnakeCase(fixCamelCaseIssues(propName))},`; + columns += `\n ${toSnakeCase(fixCamelCaseIssues(propName))},`; } }) } } else { for (let propName in properties) { if(isCustom){ - columns += `\n${propName},`; + columns += `\n ${propName},`; } else { if(propName === 'Tags' && is_tags){ continue; } - columns += `\n${toSnakeCase(fixCamelCaseIssues(propName))},`; + columns += `\n ${toSnakeCase(fixCamelCaseIssues(propName))},`; } } } if(is_tags){ - columns += `\ntag_key,`; - columns += `\ntag_value,`; + columns += `\n tag_key,`; + columns += `\n tag_value,`; } columns = columns.slice(0, -1); diff --git a/website/src/components/StackqlDeployDropdown/StackqlDeployDropdown.js b/website/src/components/StackqlDeployDropdown/StackqlDeployDropdown.js index 66a2d5094..ddbc7141c 100644 --- a/website/src/components/StackqlDeployDropdown/StackqlDeployDropdown.js +++ b/website/src/components/StackqlDeployDropdown/StackqlDeployDropdown.js @@ -91,7 +91,7 @@ function extractTemplateFromPage() { const insertH2 = document.getElementById('insert-examples') || document.getElementById('insert-example'); if (insertH2) { const els = getElementsBetweenHeadings(insertH2); - sections.insert = extractCodeFromElements(els, 'Required Properties') + sections.insert = extractCodeFromElements(els, 'All Properties') || extractCodeFromElements(els, 'create') || extractCodeFromElements(els); } @@ -169,7 +169,8 @@ function parseInsertColumns(sql) { function buildExistsQuery(parsed) { let sql = `SELECT count(*) as count\nFROM ${parsed.table}`; if (parsed.where) { - sql += `\nWHERE ${parsed.where}`; + const conditions = parsed.where.split(/\s+AND\s+/i).map(c => c.trim()); + sql += `\nWHERE ${conditions.join(' AND\n')}`; } sql += '\n;'; return sql; @@ -178,21 +179,28 @@ function buildExistsQuery(parsed) { // Builds a "statecheck" hint query - a count query where SELECT fields become // equality checks in the WHERE clause, followed by the original WHERE params. function buildStatecheckQuery(parsed) { - const fieldConditions = parsed.fields - .map(f => `${f} = {{ ${f} }}`) - .join(' AND\n'); + // Extract condition field names from WHERE clause to avoid duplicates + const whereConditionFields = new Set(); + if (parsed.where) { + parsed.where.split(/\s+AND\s+/i).forEach(c => { + const match = c.trim().match(/^\s*(\w+)\s*=/); + if (match) whereConditionFields.add(match[1].toLowerCase()); + }); + } - let whereClause = fieldConditions; + // Filter out fields already in the WHERE clause (e.g., region) + const filteredFields = parsed.fields.filter(f => !whereConditionFields.has(f.toLowerCase())); + const fieldConditions = filteredFields.map(f => `${f} = {{ ${f} }}`); + + // Collect all WHERE conditions + const allConditions = [...fieldConditions]; if (parsed.where) { - if (whereClause) { - whereClause += ' AND\n'; - } - whereClause += parsed.where; + parsed.where.split(/\s+AND\s+/i).forEach(c => allConditions.push(c.trim())); } let sql = `SELECT count(*) as count\nFROM ${parsed.table}`; - if (whereClause) { - sql += `\nWHERE \n${whereClause}`; + if (allConditions.length > 0) { + sql += `\nWHERE \n${allConditions.join(' AND\n')}`; } sql += '\n;'; return sql; @@ -234,12 +242,14 @@ function buildTemplate(sections) { parts.push(`/*+ statecheck, retries=5, retry_delay=10 */\n${buildStatecheckQuery(mutableParsed)}`); - // Build exports SELECT with only mutable fields - let exportsSql = `SELECT ${mutableParsed.fields.join(',\n')}\nFROM ${parsed.table}`; + // Use all GET fields minus region for exports + const exportFields = parsed.fields.filter(f => f.toLowerCase() !== 'region'); + let exportsSql = `SELECT\n${exportFields.join(',\n')}\nFROM ${parsed.table}`; if (parsed.where) { - exportsSql += `\nWHERE ${parsed.where}`; + const conditions = parsed.where.split(/\s+AND\s+/i).map(c => c.trim()); + exportsSql += `\nWHERE ${conditions.join(' AND\n')}`; } - exportsSql += '\n;'; + exportsSql += ';'; parts.push(`/*+ exports */\n${exportsSql}`); }