Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add indexes to tag join-tables and update tag query for threads #360

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Southclaws
Copy link
Owner

No description provided.

Copy link

vercel bot commented Jan 15, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
storyden ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 9:20pm
storyden-homepage ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 9:20pm

Copy link

coderabbitai bot commented Jan 15, 2025

📝 Walkthrough

Walkthrough

The changes introduce a comprehensive enhancement to the tagging system in the application, specifically focusing on creating many-to-many relationships between tags and nodes/posts. A new intermediary entity structure is implemented using TagNode and TagPost to manage these complex relationships. The modifications span multiple files in the internal/ent directory, updating schemas, query builders, mutation handling, and database interaction methods to support the new tagging functionality.

Changes

File Change Summary
app/resources/post/thread/db.go Updated tag querying logic to use new TagPost relationship
internal/ent/schema/node.go Added many-to-many tag relationship through node_tags
internal/ent/schema/post.go Updated tag relationship to use post_tags join table
internal/ent/schema/tag.go Modified edges to use intermediary TagNode and TagPost entities
Multiple internal/ent/* files Added new structs, methods, and query builders for TagNode and TagPost

Sequence Diagram

sequenceDiagram
    participant Client
    participant TagNodeClient
    participant TagPostClient
    participant Database

    Client->>TagNodeClient: Create TagNode
    TagNodeClient->>Database: Insert tag_nodes record
    Client->>TagPostClient: Create TagPost
    TagPostClient->>Database: Insert tag_posts record
    Client->>Database: Query nodes/posts with tags
Loading

Poem

🐰 Tagging Tales, a Rabbit's Delight

With nodes and posts now tagged just right,
Many-to-many, a data dance so neat,
Connections woven, making queries sweet!

CodeRabbit's schema, a magical sight! 🏷️

Finishing Touches

  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Southclaws Southclaws force-pushed the tag-relationship-indexes branch from ee596c6 to 8a4531d Compare January 15, 2025 21:19
@Southclaws Southclaws force-pushed the tag-relationship-indexes branch from 8a4531d to 587b4f5 Compare January 15, 2025 21:20
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (1)
internal/ent/tag_update.go (1)

Line range hint 821-873: Review the necessity of creating new entities during updates.

In the sqlSave method, the code creates new TagPostCreate instances when updating edges. This could lead to unintended data creation. Ensure that this behavior is desired, or modify the code to update existing relationships without creating new entities.

Apply this diff to remove unnecessary entity creation:

-    		createE := &TagPostCreate{config: tuo.config, mutation: newTagPostMutation(tuo.config, OpCreate)}
-    		createE.defaults()
-    		_, specE := createE.createSpec()
-    		edge.Target.Fields = specE.Fields
-    		if specE.ID.Value != nil {
-    			edge.Target.Fields = append(edge.Target.Fields, specE.ID)
-    		}
🧹 Nitpick comments (18)
internal/ent/node/node.go (1)

120-126: Consider consolidating duplicate table name constants.

The table name "tag_nodes" is defined in both TagsTable and NodeTagsTable constants. Consider using a single constant to avoid potential maintenance issues.

-// NodeTagsTable is the table that holds the node_tags relation/edge.
-NodeTagsTable = "tag_nodes"
+// NodeTagsTable is the table that holds the node_tags relation/edge.
+NodeTagsTable = TagsTable
internal/ent/tagnode_query.go (4)

1-2: Add a package documentation comment.

The file lacks a package-level comment that briefly describes the purpose of the ent package and its usage. Adding this will improve code readability and maintainability.


10-19: Organize imports according to Go conventions.

The imports can be grouped into standard library, third-party, and local package imports, separated by blank lines, to enhance code readability.

Apply this diff to organize the imports:

 import (
+	"context"
+	"fmt"
+	"math"

 	"entgo.io/ent"
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
 	"entgo.io/ent/schema/field"
+	"github.com/rs/xid"

+	"github.com/Southclaws/storyden/internal/ent/node"
+	"github.com/Southclaws/storyden/internal/ent/predicate"
+	"github.com/Southclaws/storyden/internal/ent/tag"
+	"github.com/Southclaws/storyden/internal/ent/tagnode"
 )

21-34: Consider adding context cancellation handling.

In the TagNodeQuery struct, it would be beneficial to handle context cancellation to ensure that database queries are properly canceled if the context is done.


605-705: Avoid mixing concerns in the Modify method.

The Modify method attaches custom logic to queries but returns a TagNodeSelect. This can be confusing. Consider splitting the functionality or ensuring that the method's purpose is clear.

internal/ent/tag_update.go (4)

82-111: Consider documenting the new methods for clarity.

The newly added methods for managing "post_tags" and "node_tags" edges lack comments. Adding documentation comments describing their purpose and usage would improve code maintainability.


180-221: Consider consistency in edge management methods.

The methods for clearing and removing "post_tags" and "node_tags" edges could be made consistent with the existing pattern used for other edges in the file. This would enhance readability and maintainability.


598-627: Add documentation for new methods in TagUpdateOne.

Similar to the TagUpdate struct, the new methods in TagUpdateOne lack documentation comments. Adding them will help other developers understand their purpose.


696-737: Maintain consistency in method ordering and grouping.

The newly added methods for managing "post_tags" and "node_tags" edges in TagUpdateOne should be grouped logically with related methods and ordered consistently to improve code readability.

internal/ent/mutation.go (3)

15187-15189: Inconsistent field naming in NodeMutation struct

The newly added fields node_tags, removednode_tags, and clearednode_tags use underscores in their names, while existing fields like collections, removedcollections, and clearedcollections use camelCase without underscores. For consistency with Go naming conventions, consider renaming these fields to nodeTags, removedNodeTags, and clearedNodeTags.

This naming inconsistency appears throughout the code changes. Please review all new additions to ensure consistent naming conventions.


18041-18043: Inconsistent field naming in PostMutation struct

The newly added fields post_tags, removedpost_tags, and clearedpost_tags use underscores, while existing fields use camelCase. Consider renaming them to postTags, removedPostTags, and clearedPostTags for consistency.


23140-23163: Inconsistent field naming in TagMutation struct

The newly added fields post_tags, removedpost_tags, clearedpost_tags, node_tags, removednode_tags, and clearednode_tags use underscores. To maintain consistency, consider renaming them to postTags, removedPostTags, clearedPostTags, nodeTags, removedNodeTags, and clearedNodeTags.

internal/ent/schema/tag_post.go (1)

43-47: Consider adding a composite index for better performance.

While the index on post_id is good, a composite index on (tag_id, post_id) would be beneficial for:

  1. Enforcing uniqueness of tag-post combinations
  2. Improving query performance when filtering by both fields
 func (TagPost) Indexes() []ent.Index {
 	return []ent.Index{
 		index.Fields("post_id"),
+		index.Fields("tag_id", "post_id").Unique(),
 	}
 }
internal/ent/schema/tag_node.go (1)

43-47: Consider adding a composite index for better performance.

Similar to the TagPost schema, a composite index on (tag_id, node_id) would be beneficial for:

  1. Enforcing uniqueness of tag-node combinations
  2. Improving query performance when filtering by both fields
 func (TagNode) Indexes() []ent.Index {
 	return []ent.Index{
 		index.Fields("node_id"),
+		index.Fields("tag_id", "node_id").Unique(),
 	}
 }
internal/ent/schema/post.go (1)

63-63: Consider adding indexes for the many-to-many relationship.

The change to use a join table (post_tags) for the tags relationship is good. However, since this is a many-to-many relationship that will be frequently queried, consider adding indexes to optimize query performance.

You might want to add the following indexes:

  • A composite index on (post_id, tag_id) for queries from posts to tags
  • A composite index on (tag_id, post_id) for queries from tags to posts
internal/ent/tagnode.go (1)

1-1: Consider composite indexes for performance optimization.

Since these are join tables used for many-to-many relationships, consider adding composite indexes on (tag_id, post_id) and (tag_id, node_id) pairs in addition to individual column indexes. This can improve query performance when searching for specific tag-post or tag-node combinations.

app/resources/post/thread/db.go (1)

Line range hint 404-408: Consider adding an index on the tag_post table.

Since the query now uses a join table, adding an index on (post_id, tag_id) would optimize the performance of tag lookups by post.

internal/ent/node_update.go (1)

Line range hint 849-901: Consider batch processing for tag operations.

The SQL graph specifications are correct, but consider implementing batch processing for tag operations to improve performance when handling multiple tags.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e2a0f2 and 587b4f5.

📒 Files selected for processing (47)
  • app/resources/post/thread/db.go (2 hunks)
  • internal/ent/client.go (12 hunks)
  • internal/ent/ent.go (2 hunks)
  • internal/ent/er.html (2 hunks)
  • internal/ent/hook/hook.go (1 hunks)
  • internal/ent/migrate/schema.go (3 hunks)
  • internal/ent/mutation.go (32 hunks)
  • internal/ent/node.go (3 hunks)
  • internal/ent/node/node.go (4 hunks)
  • internal/ent/node/where.go (1 hunks)
  • internal/ent/node_create.go (4 hunks)
  • internal/ent/node_query.go (9 hunks)
  • internal/ent/node_update.go (13 hunks)
  • internal/ent/post.go (3 hunks)
  • internal/ent/post/post.go (4 hunks)
  • internal/ent/post/where.go (1 hunks)
  • internal/ent/post_create.go (4 hunks)
  • internal/ent/post_query.go (9 hunks)
  • internal/ent/post_update.go (13 hunks)
  • internal/ent/predicate/predicate.go (1 hunks)
  • internal/ent/runtime.go (2 hunks)
  • internal/ent/schema/node.go (1 hunks)
  • internal/ent/schema/post.go (1 hunks)
  • internal/ent/schema/tag.go (1 hunks)
  • internal/ent/schema/tag_node.go (1 hunks)
  • internal/ent/schema/tag_post.go (1 hunks)
  • internal/ent/tag.go (3 hunks)
  • internal/ent/tag/tag.go (4 hunks)
  • internal/ent/tag/where.go (1 hunks)
  • internal/ent/tag_create.go (5 hunks)
  • internal/ent/tag_query.go (8 hunks)
  • internal/ent/tag_update.go (19 hunks)
  • internal/ent/tagnode.go (1 hunks)
  • internal/ent/tagnode/tagnode.go (1 hunks)
  • internal/ent/tagnode/where.go (1 hunks)
  • internal/ent/tagnode_create.go (1 hunks)
  • internal/ent/tagnode_delete.go (1 hunks)
  • internal/ent/tagnode_query.go (1 hunks)
  • internal/ent/tagnode_update.go (1 hunks)
  • internal/ent/tagpost.go (1 hunks)
  • internal/ent/tagpost/tagpost.go (1 hunks)
  • internal/ent/tagpost/where.go (1 hunks)
  • internal/ent/tagpost_create.go (1 hunks)
  • internal/ent/tagpost_delete.go (1 hunks)
  • internal/ent/tagpost_query.go (1 hunks)
  • internal/ent/tagpost_update.go (1 hunks)
  • internal/ent/tx.go (2 hunks)
🔇 Additional comments (114)
internal/ent/node/node.go (2)

392-404: LGTM! Ordering functions follow consistent patterns.

The implementation of ByNodeTagsCount and ByNodeTags functions aligns well with the existing ordering functions in the codebase.


482-488: Verify index creation on the tag_nodes table.

The PR objective mentions adding indexes to tag join-tables. Let's verify that the appropriate index exists on the node_id column in the tag_nodes table.

✅ Verification successful

Index is properly defined on the tag_nodes table

The schema correctly defines an index on the node_id column in the tag_nodes table through the ent framework's schema definition. This satisfies the PR objective for adding necessary indexes to tag join-tables.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for index definitions in migration files or schema files
# Look for CREATE INDEX statements in .sql files
rg -i "create\s+index.*tag_nodes.*node_id" -g "*.sql"

# Look for index definitions in schema files
rg "Index\(.*tag_nodes.*node_id" -g "*.go"

Length of output: 249


Script:

#!/bin/bash
# First, find any .sql files
echo "=== SQL Files ==="
fd -e sql

# Look for tag-related schema definitions
echo -e "\n=== Tag Schema Definitions ==="
rg -g "*.go" "type.*Tag.*struct"

# Look for any index definitions in schema
echo -e "\n=== Index Definitions ==="
rg -g "*.go" "Index\(" -A 2

# Look for tag_nodes table definition
echo -e "\n=== Tag Nodes Table Definition ==="
ast-grep --pattern 'Table = "tag_nodes"'

Length of output: 8515


Script:

#!/bin/bash
# Check the tag_node schema file for index definitions
echo "=== Tag Node Schema ==="
cat internal/ent/schema/tag_node.go

# Look for any index-related configurations in schema
echo -e "\n=== Index Configuration in Schema ==="
rg "Index|index" internal/ent/schema/tag_node.go -B 2 -A 2

Length of output: 1306

internal/ent/tagnode_update.go (1)

1-438: Code conforms to the ent framework standards

The tagnode_update.go file is generated by the ent framework. The code follows the standard patterns and conventions expected for ent generated code. No issues found.

internal/ent/tagpost_create.go (1)

1-610: Code conforms to the ent framework standards

The tagpost_create.go file is generated by the ent framework. The code adheres to the standard patterns and conventions expected for ent generated code. No issues found.

internal/ent/tagnode_create.go (1)

1-610: Code conforms to the ent framework standards

The tagnode_create.go file is generated by the ent framework. The code follows the standard patterns and conventions expected for ent generated code. No issues found.

internal/ent/tag_update.go (1)

Line range hint 275-327: Verify the edge specifications for correctness.

The edge specifications in the sqlSave method for handling "posts" relationships involve creating a TagPostCreate instance, which might not be necessary. Ensure that the edge is correctly defined for the existing relationships.

Please verify that the edge specifications correctly represent the intended relationships, and that creating new TagPostCreate instances is required.

✅ Verification successful

Edge specifications and TagPostCreate usage is correct and necessary

The creation of TagPostCreate instances is a deliberate design pattern used consistently across the codebase for handling M2M relationships between Tags and Posts. This pattern ensures proper initialization of defaults and field configurations for edge specifications.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for the necessity of TagPostCreate instances in edge specifications.

# Search for similar patterns in other update files
rg -A 5 'createE := &TagPostCreate' internal/ent/

Length of output: 6332

internal/ent/mutation.go (26)

40-41: New imports for tagnode and tagpost added

The imports for tagnode and tagpost are correctly added to the import statements.


78-79: New mutation types defined

The constants TypeTagNode and TypeTagPost are properly defined to represent the new mutation types.


16324-16377: Methods for managing NodeTags edge

The methods for handling the NodeTags edge in NodeMutation are appropriately implemented.


16811-16813: Duplicate comment


16867-16872: Duplicate comment


16895-16897: Duplicate comment


16935-16940: Duplicate comment


16975-16977: Duplicate comment


17003-17004: Duplicate comment


17060-17062: Duplicate comment


19596-19648: Methods for managing PostTags edge

The methods for handling the PostTags edge in PostMutation are correctly implemented.


20158-20160: Duplicate comment


20249-20253: Duplicate comment


20291-20293: Duplicate comment


20362-20366: Duplicate comment


20419-20421: Duplicate comment


20459-20460: Duplicate comment


20537-20539: Duplicate comment


23504-23611: Methods for managing PostTags and NodeTags edges

The methods for handling the PostTags and NodeTags edges in TagMutation are properly implemented.


23772-23777: Duplicate comment


23832-23836: Duplicate comment


23863-23873: Duplicate comment


23891-23895: Duplicate comment


23909-23912: Duplicate comment


23938-23943: Duplicate comment


23948-24918: New mutation types TagNodeMutation and TagPostMutation added

The TagNodeMutation and TagPostMutation types have been introduced and correctly implement methods for managing mutations on TagNode and TagPost entities.

internal/ent/schema/tag.go (1)

27-28: LGTM! Well-structured many-to-many relationships.

The implementation correctly uses join tables for tag relationships with posts and nodes, which is the recommended approach for many-to-many relationships in ent.

internal/ent/schema/tag_post.go (1)

20-41: LGTM! Well-structured join table schema.

The implementation includes proper field types, required constraints, and cascade delete behavior which ensures data consistency.

internal/ent/schema/node.go (1)

61-61: LGTM! Consistent implementation of many-to-many relationship.

The change properly establishes the many-to-many relationship with tags through the TagNode join table, maintaining consistency with the Tag schema.

internal/ent/tagpost_delete.go (1)

1-88: Generated code looks good!

The generated code follows standard ent patterns and includes proper error handling, predicate support, and both bulk and single-entity deletion capabilities.

internal/ent/tagnode_delete.go (1)

1-88: Generated code looks good!

The generated code follows the same standard ent patterns as tagpost_delete.go and includes all necessary functionality for managing TagNode deletions.

internal/ent/predicate/predicate.go (1)

80-85: Generated predicates look good!

The new predicate types for TagNode and TagPost follow the established pattern and are properly documented.

internal/ent/tagpost.go (1)

17-161: Implementation looks good!

The TagPost entity is well-structured with:

  • Proper type safety for ID fields
  • Comprehensive error handling for edge relationships
  • Clear transaction management
internal/ent/tagnode.go (1)

17-161: Implementation looks good!

The TagNode entity is well-structured with:

  • Proper type safety for ID fields
  • Comprehensive error handling for edge relationships
  • Clear transaction management
internal/ent/tag.go (4)

39-42: LGTM: New edge fields properly defined.

The new edge fields PostTags and NodeTags are correctly added to the TagEdges struct, following the established pattern.


45-45: LGTM: Array size updated for new edges.

The loadedTypes array size is correctly updated to accommodate the two new edges.


75-91: LGTM: Edge accessor methods properly implemented.

The PostTagsOrErr and NodeTagsOrErr methods are correctly implemented, following the same pattern as other edge accessors.


165-173: LGTM: Query methods properly implemented.

The QueryPostTags and QueryNodeTags methods are correctly implemented, following the established pattern for edge queries.

internal/ent/tag/tag.go (4)

28-31: LGTM: New edge constants properly defined.

The edge constants for post_tags and node_tags are correctly added.


49-62: LGTM: Table and column constants properly defined.

The table and column constants for the new relationships are correctly defined, maintaining consistency with existing patterns.


163-189: LGTM: Ordering functions properly implemented.

The new ordering functions for post_tags and node_tags follow the established patterns and are correctly implemented.


211-224: LGTM: Step functions properly implemented.

The new step functions for post_tags and node_tags relationships are correctly implemented, following the established patterns.

internal/ent/tag/where.go (2)

243-264: LGTM: PostTags predicates properly implemented.

The HasPostTags and HasPostTagsWith predicates are correctly implemented, following the established patterns.


266-287: LGTM: NodeTags predicates properly implemented.

The HasNodeTags and HasNodeTagsWith predicates are correctly implemented, following the established patterns.

internal/ent/tagpost/where.go (2)

207-251: LGTM: Edge predicates properly implemented.

The HasTag, HasTagWith, HasPost, and HasPostWith predicates are correctly implemented, following the established patterns.


107-135: Consider the necessity of string operations on ID fields.

The implementation includes string-based operations (Contains, HasPrefix, HasSuffix, EqualFold, ContainsFold) on tag_id field which is an xid.ID. These operations might not be practically useful for ID fields and could potentially be confusing to users.

Run this script to check if these operations are used in the codebase:

internal/ent/tagnode/where.go (1)

1-266: Auto-generated code looks good!

The code follows the standard ent framework patterns for predicate generation, with well-structured query builders and proper edge handling.

internal/ent/tx.go (1)

65-68: LGTM! Transaction client properly extended.

The new TagNode and TagPost clients are correctly integrated into the transaction system, following the established patterns.

Also applies to: 224-225

internal/ent/tagpost_update.go (1)

1-438: Auto-generated update operations look good!

The code follows ent framework patterns with proper validation, error handling, and edge mutations for both bulk and single-entity updates.

app/resources/post/thread/db.go (1)

Line range hint 404-408: Query updated to use new tag-post relationship model.

The change from HasPostsWith to HasPostTagsWith correctly reflects the architectural shift to using a join table for tag-post relationships.

internal/ent/node.go (3)

79-80: LGTM! The NodeEdges struct is correctly updated.

The changes properly add support for the new TagNode relationship and correctly update the loadedTypes array size.

Also applies to: 85-85


177-184: LGTM! The NodeTagsOrErr method is well-implemented.

The method follows the established pattern and correctly handles error cases.


380-384: LGTM! The QueryNodeTags method is properly implemented.

The method follows the established pattern for edge queries.

internal/ent/hook/hook.go (2)

300-310: LGTM! The TagNodeFunc type and its Mutate method are well-implemented.

The implementation follows the established pattern for hook types.


312-322: LGTM! The TagPostFunc type and its Mutate method are well-implemented.

The implementation follows the established pattern for hook types.

internal/ent/ent.go (2)

39-40: LGTM! The imports are correctly added.

The new imports follow the established pattern.


125-126: LGTM! The column checks are properly added.

The new column checks follow the established pattern.

internal/ent/tag_create.go (4)

19-20: LGTM! The imports are correctly added.

The new imports follow the established pattern.


111-124: LGTM! The TagPost relationship methods are well-implemented.

The methods follow the established pattern and correctly handle ID conversion.


126-139: LGTM! The TagNode relationship methods are well-implemented.

The methods follow the established pattern and correctly handle ID conversion.


305-336: LGTM! The edge specifications are properly implemented.

The edge specifications correctly define one-to-many relationships for both TagPost and TagNode.

internal/ent/post.go (4)

Line range hint 83-84: LGTM: Edge constant properly defined.

The EdgePostTags constant correctly defines the edge name for post-tag relationships in mutations.


Line range hint 172-178: LGTM: Table and column constants properly defined.

The constants properly define the database structure for post-tag relationships:

  • PostTagsTable defines the join table
  • PostTagsInverseTable avoids circular dependencies
  • PostTagsColumn specifies the foreign key column

Line range hint 530-542: LGTM: Ordering functions properly implemented.

The ordering functions provide necessary functionality for sorting results:

  • ByPostTagsCount allows ordering by the number of tags
  • ByPostTags enables ordering by tag-specific terms

Line range hint 648-654: LGTM: SQL graph step properly defined.

The newPostTagsStep function correctly sets up the SQL graph step for the post-tag relationship with proper edge type (O2M) and table configuration.

internal/ent/tagpost_query.go (3)

21-34: LGTM: Query builder struct properly defined.

The TagPostQuery struct follows ent's standard patterns with all necessary fields for query building:

  • Configuration and context
  • Order and predicates
  • Edge loading support
  • SQL query building

67-87: LGTM: Edge query methods properly implemented.

The QueryTag and QueryPost methods correctly implement the edge traversal logic:

  • Proper error handling
  • Correct SQL graph step configuration
  • Appropriate neighbor selection

Also applies to: 89-109


408-451: LGTM: SQL query execution properly implemented.

The sqlAll method correctly handles:

  • Node scanning and assignment
  • Edge loading
  • Error handling
  • Query specification
internal/ent/tag_query.go (3)

35-36: LGTM: New relationship fields properly added.

The withPostTags and withNodeTags fields are correctly added to support eager loading of tag relationships.


521-526: LGTM: Loaded types array properly updated.

The loadedTypes array size is correctly updated to accommodate the new relationships:

  • Increased from 3 to 5 elements
  • Properly tracks loading state of new relationships

771-800: LGTM: Post tags loading function properly implemented.

The loadPostTags function correctly implements the relationship loading logic:

  • Proper foreign key handling
  • Correct error handling
  • Appropriate node assignment
internal/ent/node/where.go (2)

1126-1135: Implementation of HasNodeTags looks good!

The function correctly implements the one-to-many relationship between nodes and tag_nodes using the standard ent predicate pattern.


1137-1147: HasNodeTagsWith implementation is correct!

The function properly implements predicate chaining for the node_tags edge, following ent's established patterns.

internal/ent/migrate/schema.go (3)

794-831: Well-designed schema for tag_nodes table!

The schema includes appropriate indexes for both lookup performance (tagnode_node_id) and data integrity (unique constraint on tag_id + node_id pair). The cascade delete behavior ensures referential integrity.


832-869: TagPosts table schema maintains consistency!

The schema follows the same well-designed pattern as tag_nodes, with appropriate indexes and constraints for efficient querying and data integrity.


1046-1047: Correct registration of new tables!

The tables are properly added to the Tables registry while maintaining alphabetical order.

internal/ent/runtime.go (1)

947-996: Runtime configuration for TagNode and TagPost is properly implemented!

The code correctly sets up mixins, field descriptors, default values, and validators following ent's patterns.

internal/ent/node_query.go (3)

280-300: QueryNodeTags implementation is correct!

The edge traversal is properly implemented following ent's query builder patterns, with correct table and column references.


633-642: WithNodeTags eager loading is properly implemented!

The method correctly follows ent's patterns for configuring eager loading of edges.


1237-1266: loadNodeTags implementation is robust!

The loading logic properly handles foreign key relationships with appropriate error handling and clear error messages.

internal/ent/post/where.go (2)

1379-1388: LGTM! The HasPostTags predicate is correctly implemented.

The function follows ent's standard pattern for edge predicates, properly setting up the graph traversal for the "post_tags" edge.


1390-1400: LGTM! The HasPostTagsWith predicate is correctly implemented.

The function properly extends the basic predicate with additional filtering capabilities, following ent's conventions.

internal/ent/node_create.go (2)

340-354: LGTM! The node tag relationship methods are correctly implemented.

Both methods follow ent's standard pattern for managing many-to-many relationships:

  • AddNodeTagIDs for direct ID management
  • AddNodeTags as a convenience wrapper

614-620: LGTM! The tag relationship handling in createSpec is correct.

The implementation properly initializes the edge specification with default values and handles the ID field appropriately.

internal/ent/post_query.go (3)

421-441: LGTM! The QueryPostTags method is correctly implemented.

The method properly sets up the graph traversal for the "post_tags" edge, following ent's conventions for edge queries.


1052-1058: LGTM! The eager loading implementation is correct.

The code properly handles the eager loading of post tags, including initialization and assignment of the loaded relationships.


1632-1661: LGTM! The loadPostTags method is correctly implemented.

The method follows ent's patterns for loading relationships:

  • Proper handling of foreign keys
  • Correct error handling
  • Efficient batch loading
internal/ent/post_create.go (2)

451-464: LGTM! The post tag relationship methods are correctly implemented.

Both methods follow ent's standard pattern for managing relationships:

  • AddPostTagIDs for direct ID management
  • AddPostTags as a convenience wrapper

894-909: LGTM! The tag relationship handling in edge specifications is correct.

The implementation properly sets up the database relationships with correct table and column specifications.

internal/ent/node_update.go (3)

21-21: Import changes look good.

The addition of the tagnode import is necessary for implementing the new tag relationship functionality.


382-396: Methods for adding node tags are well implemented.

The AddNodeTagIDs and AddNodeTags methods follow the established ent patterns for relationship management and are implemented correctly.


531-550: Tag removal methods are properly implemented.

The ClearNodeTags, RemoveNodeTagIDs, and RemoveNodeTags methods complete the CRUD operations for tag relationships and follow consistent patterns.

internal/ent/post_update.go (2)

523-536: Post tag management implementation mirrors node tag management.

The implementation maintains consistency with the node tag management patterns, which is good for maintainability and understanding of the codebase.

Also applies to: 783-802, 2072-2085


Line range hint 2558-2610: SQL specifications match node implementation.

The SQL graph specifications mirror those in node_update.go. The same batch processing optimization suggested for nodes would be beneficial here.

internal/ent/client.go (9)

43-44: LGTM: Import statements for new tag-related packages.

The imports for tagnode and tagpost packages are correctly added to support the new tag functionality.


102-105: LGTM: New client fields for tag relationships.

The TagNode and TagPost client fields are properly added to the Client struct with clear documentation.


141-142: LGTM: Client initialization for tag relationships.

The initialization of TagNode and TagPost clients is correctly implemented in the init method.


3693-3707: LGTM: Node query method for tag relationships.

The QueryNodeTags method is correctly implemented to query the node_tags edge of a Node entity using proper SQL graph traversal.


4263-4277: LGTM: Post query method for tag relationships.

The QueryPostTags method is correctly implemented to query the post_tags edge of a Post entity using proper SQL graph traversal.


5072-5102: LGTM: Tag query methods for relationships.

The QueryPostTags and QueryNodeTags methods are correctly implemented to query the tag relationships from the Tag entity's perspective.


5129-5292: LGTM: TagNode client implementation.

The TagNodeClient implementation follows the standard pattern with all necessary methods for CRUD operations and relationship queries.


5294-5457: LGTM: TagPost client implementation.

The TagPostClient implementation follows the standard pattern with all necessary methods for CRUD operations and relationship queries.


5465-5465: LGTM: Hook and interceptor type updates.

The hooks and interceptors structs are correctly updated to include the new tag-related clients.

Also applies to: 5471-5471

internal/ent/er.html (3)

246-250: LGTM: TagNode entity definition.

The TagNode entity is correctly defined with all necessary fields: id, tag_id, and node_id.


251-254: LGTM: TagPost entity definition.

The TagPost entity is correctly defined with all necessary fields: id, tag_id, and post_id.


307-310: LGTM: Tag relationship definitions.

The relationships between tags and their associated entities are correctly defined:

  • TagNode to Tag (many-to-one)
  • TagNode to Node (many-to-one)
  • TagPost to Tag (many-to-one)
  • TagPost to Post (many-to-one)
internal/ent/post/post.go (2)

83-84: LGTM! Constants are well-defined and documented.

The new constants for post tags follow the established naming pattern and are properly documented.

Also applies to: 172-178


530-542: LGTM! Ordering functions are consistent with the codebase.

The new ordering functions ByPostTagsCount and ByPostTags follow the same implementation pattern as other ordering functions in the file.

Comment on lines +89 to +109
// QueryNode chains the current query on the "node" edge.
func (tnq *TagNodeQuery) QueryNode() *NodeQuery {
query := (&NodeClient{config: tnq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := tnq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := tnq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(tagnode.Table, tagnode.FieldID, selector),
sqlgraph.To(node.Table, node.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, tagnode.NodeTable, tagnode.NodeColumn),
)
fromU = sqlgraph.SetNeighbors(tnq.driver.Dialect(), step)
return fromU, nil
}
return query
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Check for possible nil pointer dereference.

Similarly, in the QueryNode method, add a nil check for tnq.sql after tnq.prepareQuery(ctx) to prevent potential runtime errors.

Apply this diff:

 func (tnq *TagNodeQuery) QueryNode() *NodeQuery {
 	query := (&NodeClient{config: tnq.config}).Query()
 	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
 		if err := tnq.prepareQuery(ctx); err != nil {
 			return nil, err
 		}
+		if tnq.sql == nil {
+			return nil, fmt.Errorf("unexpected nil selector")
+		}
 		selector := tnq.sqlQuery(ctx)
 		if err := selector.Err(); err != nil {
 			return nil, err
 		}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +570 to +603
func (tnq *TagNodeQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(tnq.driver.Dialect())
t1 := builder.Table(tagnode.Table)
columns := tnq.ctx.Fields
if len(columns) == 0 {
columns = tagnode.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if tnq.sql != nil {
selector = tnq.sql
selector.Select(selector.Columns(columns...)...)
}
if tnq.ctx.Unique != nil && *tnq.ctx.Unique {
selector.Distinct()
}
for _, m := range tnq.modifiers {
m(selector)
}
for _, p := range tnq.predicates {
p(selector)
}
for _, p := range tnq.order {
p(selector)
}
if offset := tnq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := tnq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure proper handling of default limit for offset queries.

In the sqlQuery method, when offset is set without a limit, the default limit is set to math.MaxInt32. This could lead to performance issues. Consider setting a reasonable default limit or requiring a limit to be set when using offset.

Apply this diff to set a reasonable default limit:

 		if offset := tnq.ctx.Offset; offset != nil {
 			// limit is mandatory for offset clause. We start
 			// with default value, and override it below if needed.
-			selector.Offset(*offset).Limit(math.MaxInt32)
+			defaultLimit := 100
+			selector.Offset(*offset).Limit(defaultLimit)
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (tnq *TagNodeQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(tnq.driver.Dialect())
t1 := builder.Table(tagnode.Table)
columns := tnq.ctx.Fields
if len(columns) == 0 {
columns = tagnode.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if tnq.sql != nil {
selector = tnq.sql
selector.Select(selector.Columns(columns...)...)
}
if tnq.ctx.Unique != nil && *tnq.ctx.Unique {
selector.Distinct()
}
for _, m := range tnq.modifiers {
m(selector)
}
for _, p := range tnq.predicates {
p(selector)
}
for _, p := range tnq.order {
p(selector)
}
if offset := tnq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := tnq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
func (tnq *TagNodeQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(tnq.driver.Dialect())
t1 := builder.Table(tagnode.Table)
columns := tnq.ctx.Fields
if len(columns) == 0 {
columns = tagnode.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if tnq.sql != nil {
selector = tnq.sql
selector.Select(selector.Columns(columns...)...)
}
if tnq.ctx.Unique != nil && *tnq.ctx.Unique {
selector.Distinct()
}
for _, m := range tnq.modifiers {
m(selector)
}
for _, p := range tnq.predicates {
p(selector)
}
for _, p := range tnq.order {
p(selector)
}
if offset := tnq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
defaultLimit := 100
selector.Offset(*offset).Limit(defaultLimit)
}
if limit := tnq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}

Comment on lines +67 to +87
// QueryTag chains the current query on the "tag" edge.
func (tnq *TagNodeQuery) QueryTag() *TagQuery {
query := (&TagClient{config: tnq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := tnq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := tnq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(tagnode.Table, tagnode.FieldID, selector),
sqlgraph.To(tag.Table, tag.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, tagnode.TagTable, tagnode.TagColumn),
)
fromU = sqlgraph.SetNeighbors(tnq.driver.Dialect(), step)
return fromU, nil
}
return query
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Check for possible nil pointer dereference.

In the QueryTag method, after calling tnq.prepareQuery(ctx), it's good practice to check if tnq.sql is not nil before proceeding, to avoid potential nil pointer dereferences.

Apply this diff to add the nil check:

 func (tnq *TagNodeQuery) QueryTag() *TagQuery {
 	query := (&TagClient{config: tnq.config}).Query()
 	query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
 		if err := tnq.prepareQuery(ctx); err != nil {
 			return nil, err
 		}
+		if tnq.sql == nil {
+			return nil, fmt.Errorf("unexpected nil selector")
+		}
 		selector := tnq.sqlQuery(ctx)
 		if err := selector.Err(); err != nil {
 			return nil, err
 		}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +441 to +485
if tu.mutation.PostTagsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: tag.PostTagsTable,
Columns: []string{tag.PostTagsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(tagpost.FieldID, field.TypeString),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := tu.mutation.RemovedPostTagsIDs(); len(nodes) > 0 && !tu.mutation.PostTagsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: tag.PostTagsTable,
Columns: []string{tag.PostTagsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(tagpost.FieldID, field.TypeString),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := tu.mutation.PostTagsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: tag.PostTagsTable,
Columns: []string{tag.PostTagsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(tagpost.FieldID, field.TypeString),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure correct relationship direction in edge specifications.

In the sqlSave method, for the "post_tags" edge, the Inverse field is set to true, which may not accurately represent the relationship direction. Verify that the edge specification correctly models the intended relationship between Tag and TagPost.

Apply this diff if the edge direction is incorrect:

    		edge := &sqlgraph.EdgeSpec{
-    			Rel:     sqlgraph.O2M,
-    			Inverse: true,
+    			Rel:     sqlgraph.O2M,
+    			Inverse: false,

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +1 to +110
const (
// Label holds the string label denoting the tagpost type in the database.
Label = "tag_post"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldTagID holds the string denoting the tag_id field in the database.
FieldTagID = "tag_id"
// FieldPostID holds the string denoting the post_id field in the database.
FieldPostID = "post_id"
// EdgeTag holds the string denoting the tag edge name in mutations.
EdgeTag = "tag"
// EdgePost holds the string denoting the post edge name in mutations.
EdgePost = "post"
// Table holds the table name of the tagpost in the database.
Table = "tag_posts"
// TagTable is the table that holds the tag relation/edge.
TagTable = "tag_posts"
// TagInverseTable is the table name for the Tag entity.
// It exists in this package in order to avoid circular dependency with the "tag" package.
TagInverseTable = "tags"
// TagColumn is the table column denoting the tag relation/edge.
TagColumn = "tag_id"
// PostTable is the table that holds the post relation/edge.
PostTable = "tag_posts"
// PostInverseTable is the table name for the Post entity.
// It exists in this package in order to avoid circular dependency with the "post" package.
PostInverseTable = "posts"
// PostColumn is the table column denoting the post relation/edge.
PostColumn = "post_id"
)

// Columns holds all SQL columns for tagpost fields.
var Columns = []string{
FieldID,
FieldTagID,
FieldPostID,
}

// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}

var (
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() xid.ID
// IDValidator is a validator for the "id" field. It is called by the builders before save.
IDValidator func(string) error
)

// OrderOption defines the ordering options for the TagPost queries.
type OrderOption func(*sql.Selector)

// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}

// ByTagID orders the results by the tag_id field.
func ByTagID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldTagID, opts...).ToFunc()
}

// ByPostID orders the results by the post_id field.
func ByPostID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPostID, opts...).ToFunc()
}

// ByTagField orders the results by tag field.
func ByTagField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newTagStep(), sql.OrderByField(field, opts...))
}
}

// ByPostField orders the results by post field.
func ByPostField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newPostStep(), sql.OrderByField(field, opts...))
}
}
func newTagStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(TagInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, TagTable, TagColumn),
)
}
func newPostStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(PostInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, PostTable, PostColumn),
)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Add index for tag_id column in TagPost schema

The schema only defines an index for post_id, but tag_id should also be indexed for optimal query performance. Update the Indexes() method in internal/ent/schema/tag_post.go:

func (TagPost) Indexes() []ent.Index {
    return []ent.Index{
        index.Fields("post_id"),
        index.Fields("tag_id"),  // Add this index
    }
}
🔗 Analysis chain

Verify indexes on tag_posts table.

The PR objective mentions adding indexes to tag join-tables. While this generated code looks correct, we should verify that the appropriate indexes are defined in the schema file.

Run the following script to check the schema definition:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if indexes are defined in the schema file
# Expected: Find index definitions for tag_id and post_id columns

rg -A 10 'func \(.*TagPost\) Fields\(\)' internal/ent/schema/

Length of output: 671


Script:

#!/bin/bash
# Description: Check if Indexes() method is defined for TagPost
rg -A 5 'func \(.*TagPost\) Indexes\(\)' internal/ent/schema/tag_post.go

Length of output: 166

Comment on lines +1 to +110
const (
// Label holds the string label denoting the tagnode type in the database.
Label = "tag_node"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldTagID holds the string denoting the tag_id field in the database.
FieldTagID = "tag_id"
// FieldNodeID holds the string denoting the node_id field in the database.
FieldNodeID = "node_id"
// EdgeTag holds the string denoting the tag edge name in mutations.
EdgeTag = "tag"
// EdgeNode holds the string denoting the node edge name in mutations.
EdgeNode = "node"
// Table holds the table name of the tagnode in the database.
Table = "tag_nodes"
// TagTable is the table that holds the tag relation/edge.
TagTable = "tag_nodes"
// TagInverseTable is the table name for the Tag entity.
// It exists in this package in order to avoid circular dependency with the "tag" package.
TagInverseTable = "tags"
// TagColumn is the table column denoting the tag relation/edge.
TagColumn = "tag_id"
// NodeTable is the table that holds the node relation/edge.
NodeTable = "tag_nodes"
// NodeInverseTable is the table name for the Node entity.
// It exists in this package in order to avoid circular dependency with the "node" package.
NodeInverseTable = "nodes"
// NodeColumn is the table column denoting the node relation/edge.
NodeColumn = "node_id"
)

// Columns holds all SQL columns for tagnode fields.
var Columns = []string{
FieldID,
FieldTagID,
FieldNodeID,
}

// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}

var (
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() xid.ID
// IDValidator is a validator for the "id" field. It is called by the builders before save.
IDValidator func(string) error
)

// OrderOption defines the ordering options for the TagNode queries.
type OrderOption func(*sql.Selector)

// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}

// ByTagID orders the results by the tag_id field.
func ByTagID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldTagID, opts...).ToFunc()
}

// ByNodeID orders the results by the node_id field.
func ByNodeID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldNodeID, opts...).ToFunc()
}

// ByTagField orders the results by tag field.
func ByTagField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newTagStep(), sql.OrderByField(field, opts...))
}
}

// ByNodeField orders the results by node field.
func ByNodeField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newNodeStep(), sql.OrderByField(field, opts...))
}
}
func newTagStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(TagInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, TagTable, TagColumn),
)
}
func newNodeStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(NodeInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, NodeTable, NodeColumn),
)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Add missing index on tag_id column

The tag_nodes table currently only has an index on node_id. Since this is a join table, it should have indexes on both foreign key columns to ensure efficient querying from both the tags and nodes side.

  • Add index on tag_id column in internal/ent/schema/tag_node.go
🔗 Analysis chain

Verify indexes on tag_nodes table.

Similar to the tag_posts table, we should verify that appropriate indexes are defined for the tag_nodes join table in the schema file.

Run the following script to check the schema definition:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if indexes are defined in the schema file
# Expected: Find index definitions for tag_id and node_id columns

rg -A 10 'func \(.*TagNode\) Fields\(\)' internal/ent/schema/

Length of output: 671


Script:

#!/bin/bash
# Search for Indexes() method and unique constraints in tag_node schema
rg -A 10 'func \(.*TagNode\) (Indexes|Annotations)\(\)' internal/ent/schema/tag_node.go

# Also check for any unique constraints in the schema
ast-grep --pattern 'field.$_("$_").$$$Unique()' internal/ent/schema/tag_node.go

Length of output: 263

Comment on lines +177 to +205
// PostIDContains applies the Contains predicate on the "post_id" field.
func PostIDContains(v xid.ID) predicate.TagPost {
vc := v.String()
return predicate.TagPost(sql.FieldContains(FieldPostID, vc))
}

// PostIDHasPrefix applies the HasPrefix predicate on the "post_id" field.
func PostIDHasPrefix(v xid.ID) predicate.TagPost {
vc := v.String()
return predicate.TagPost(sql.FieldHasPrefix(FieldPostID, vc))
}

// PostIDHasSuffix applies the HasSuffix predicate on the "post_id" field.
func PostIDHasSuffix(v xid.ID) predicate.TagPost {
vc := v.String()
return predicate.TagPost(sql.FieldHasSuffix(FieldPostID, vc))
}

// PostIDEqualFold applies the EqualFold predicate on the "post_id" field.
func PostIDEqualFold(v xid.ID) predicate.TagPost {
vc := v.String()
return predicate.TagPost(sql.FieldEqualFold(FieldPostID, vc))
}

// PostIDContainsFold applies the ContainsFold predicate on the "post_id" field.
func PostIDContainsFold(v xid.ID) predicate.TagPost {
vc := v.String()
return predicate.TagPost(sql.FieldContainsFold(FieldPostID, vc))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Remove unused string operation predicates on ID fields

These string-based predicates (Contains, HasPrefix, HasSuffix, EqualFold, ContainsFold) on post_id fields are:

  • Unused in the codebase
  • Not practically useful for ID fields which should use exact matching
  • Potentially problematic as they could lead to incorrect matches
🔗 Analysis chain

Consider the necessity of string operations on ID fields.

Similar to the tag_id field, the implementation includes string-based operations on post_id field which is an xid.ID. These operations might not be practically useful for ID fields.

Run this script to check if these operations are used in the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of string operations on post_id
# Test: Search for any calls to these functions. Expect: No matches if unused.

rg "PostIDContains|PostIDHasPrefix|PostIDHasSuffix|PostIDEqualFold|PostIDContainsFold"

Length of output: 6925


Script:

#!/bin/bash
# Search for actual usage of these predicates in function calls
rg "\.(PostIDContains|PostIDHasPrefix|PostIDHasSuffix|PostIDEqualFold|PostIDContainsFold)\(" --type go

Length of output: 104

Comment on lines +648 to +654
func newPostTagsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(PostTagsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, PostTagsTable, PostTagsColumn),
)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

The relationship type is incorrectly defined as one-to-many

The newPostTagsStep function incorrectly defines a one-to-many (O2M) relationship, but the database schema clearly shows this is a many-to-many relationship:

  • The tag_posts table is a junction table with tag_id and post_id foreign keys
  • Both foreign keys have CASCADE delete behavior
  • The table structure enables multiple posts to be associated with multiple tags

The relationship type should be changed from O2M to M2M in the sqlgraph.Edge call.

🔗 Analysis chain

Verify the relationship type between posts and tags.

The newPostTagsStep function defines a one-to-many (O2M) relationship from posts to post tags with true for back reference. However, the table structure (tag_posts) suggests this might be a many-to-many relationship. Please verify if this is the intended relationship type.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the schema definition and other references to verify the relationship type

# Look for schema definitions containing tag_posts table
ast-grep --pattern 'Table($_, "tag_posts")'

# Look for other references to tag_posts table
rg -A 5 'tag_posts'

Length of output: 5669

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant