Skip to content

Conversation

@mertcanaltin
Copy link
Member

@mertcanaltin mertcanaltin commented Jan 6, 2026

Fixes: #61268

add limits property to databaseSync

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/sqlite

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Jan 6, 2026
@mertcanaltin mertcanaltin requested a review from louwers January 6, 2026 20:46
Copy link
Contributor

@louwers louwers left a comment

Choose a reason for hiding this comment

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

Should we add SQLITE_MAX_LENGTH etc. as constants? https://sqlite.org/limits.html

@mertcanaltin
Copy link
Member Author

Should we add SQLITE_MAX_LENGTH etc. as constants? https://sqlite.org/limits.html

SQLITE_MAX are compile-time preprocessor macros, so they can't be exported directly at runtime. however, the default values returned by db.limits are exactly these SQLITE_MAX values (assuming SQLite was compiled with default settings).

so db.limits.length returns 1000000000 which equals SQLITE_MAX_LENGTH.

if you want explicit constants, i could add SQLITE_LIMIT (the enum IDs used with sqlite3_limit()) to the constants object.
let me know what you think would be most useful.

mertcanaltin and others added 9 commits January 7, 2026 00:39
Co-authored-by: Anna Henningsen <[email protected]>
Co-authored-by: Anna Henningsen <[email protected]>
Co-authored-by: Anna Henningsen <[email protected]>
Co-authored-by: Anna Henningsen <[email protected]>
Co-authored-by: Anna Henningsen <[email protected]>
Co-authored-by: Anna Henningsen <[email protected]>
Co-authored-by: Anna Henningsen <[email protected]>
Co-authored-by: Anna Henningsen <[email protected]>
@mertcanaltin
Copy link
Member Author

@addaleax thanks for reviews, I tried solve

@mertcanaltin
Copy link
Member Author

@Renegade334 Thank you, I tried to apply what you said.

@louwers
Copy link
Contributor

louwers commented Jan 9, 2026

Would it be possible to interpret Infinity as a special value?

Having a setter that accepts different types from the corresponding getter feels wrong to me.

Also, I would except that 'resetting' a limit means it goes back to the value that was initially provided to the constructor. Not that it takes on the highest value (which is the same as the default value). Setting it to Infinity leaves little room for alternate interpretations.

@mertcanaltin
Copy link
Member Author

mertcanaltin commented Jan 11, 2026

+1 Of course! I used Infinity instead of Null and updated the test documents.

@mertcanaltin mertcanaltin requested a review from louwers January 11, 2026 10:46
@louwers
Copy link
Contributor

louwers commented Jan 11, 2026

Neat, is @Renegade334 on board with that too?

@Renegade334
Copy link
Member

Renegade334 commented Jan 11, 2026

SGTM!

The only alternative thought I'd have would be making -1 the magic number. It's perhaps less semantically on-the-button than Infinity, but the handling becomes a lot more straightforward.

@mertcanaltin
Copy link
Member Author

Hi, I think I need a review here. @Renegade334 @louwers

Isolate* isolate = info.GetIsolate();
LocalVector<Value> names(isolate);

for (size_t i = 0; i < kLimitMapping.size(); ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

I need "i" here, so I'm using the traditional for method.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why is it needed?

Copy link
Contributor

Choose a reason for hiding this comment

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

      // Iterate through known limit names and extract values
      for (const auto& [js_name, sqlite_limit_id] : kLimitMapping) {
        Local<String> key;
        if (!String::NewFromUtf8(env->isolate(),
                                 js_name.data(),
                                 NewStringType::kNormal,
                                 js_name.size())
                 .ToLocal(&key)) {
          return;
        }

        Local<Value> val;
        if (!limits_obj->Get(env->context(), key).ToLocal(&val)) {
          return;
        }

        if (!val->IsUndefined()) {
          if (!val->IsInt32()) {
            std::string msg = "The \"options.limits." +
                              std::string(js_name) +
                              "\" argument must be an integer.";
            THROW_ERR_INVALID_ARG_TYPE(env->isolate(), msg);
            return;
          }

          int limit_val = val.As<Int32>()->Value();
          if (limit_val < 0) {
            std::string msg = "The \"options.limits." +
                              std::string(js_name) +
                              "\" argument must be non-negative.";
            THROW_ERR_OUT_OF_RANGE(env->isolate(), msg);
            return;
          }

          open_config.set_initial_limit(sqlite_limit_id, limit_val);
        }
      }

Copy link
Contributor

@louwers louwers left a comment

Choose a reason for hiding this comment

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

Left some comments. But a collaborator will have to review this as well.

@mertcanaltin
Copy link
Member Author

Left some comments. But a collaborator will have to review this as well.

thanks for reviews 🙏

Co-authored-by: Bart Louwers <[email protected]>
LocalVector<Value> names(isolate);

for (size_t i = 0; i < kLimitMapping.size(); ++i) {
for (const auto& mapping : kLimitMapping) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider using a structured binding declaration.

initial_limits_.at(limit_id) = value;
}

inline const std::array<std::optional<int>, kNumSqliteLimits>&
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not what I meant. If another limit gets added the limit number needs to be manually updated, which is error-prone. Instead you can use

Suggested change
inline const std::array<std::optional<int>, kNumSqliteLimits>&
inline const std::array<std::optional<int>, kLimitMapping.size()>&

which works becauze the .size() method is constexpr.


// Apply initial limits
const auto& limits = open_config_.initial_limits();
for (size_t i = 0; i < limits.size(); ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You're right that here a regular for-loop has to be used. Well, C++23 will allow std::views::enumerate. But we're not there yet

Nit: change i to limit_id to avoid a single letter variable, and make it more clear what it represents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sqlite: allow setting limits on inputs

5 participants