Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rqlite for openSUSE:Factory checked 
in at 2025-06-10 09:04:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rqlite (Old)
 and      /work/SRC/openSUSE:Factory/.rqlite.new.19631 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rqlite"

Tue Jun 10 09:04:23 2025 rev:17 rq:1283869 version:8.37.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/rqlite/rqlite.changes    2025-06-03 
17:53:06.724541925 +0200
+++ /work/SRC/openSUSE:Factory/.rqlite.new.19631/rqlite.changes 2025-06-10 
09:07:50.749785743 +0200
@@ -1,0 +2,12 @@
+Sat Jun  7 17:02:14 UTC 2025 - Andreas Stieger <andreas.stie...@gmx.de>
+
+- Update to version 8.37.4:
+  * Upgrade SQL parser
+
+-------------------------------------------------------------------
+Sat Jun  7 07:24:23 UTC 2025 - Andreas Stieger <andreas.stie...@gmx.de>
+
+- Update to version 8.37.3:
+  * Upgrade SQL parser
+
+-------------------------------------------------------------------

Old:
----
  rqlite-8.37.2.tar.xz

New:
----
  rqlite-8.37.4.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rqlite.spec ++++++
--- /var/tmp/diff_new_pack.oRRubM/_old  2025-06-10 09:07:52.489857671 +0200
+++ /var/tmp/diff_new_pack.oRRubM/_new  2025-06-10 09:07:52.513858664 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           rqlite
-Version:        8.37.2
+Version:        8.37.4
 Release:        0
 Summary:        Distributed relational database built on SQLite
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.oRRubM/_old  2025-06-10 09:07:52.873873545 +0200
+++ /var/tmp/diff_new_pack.oRRubM/_new  2025-06-10 09:07:52.929875860 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/rqlite/rqlite.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v8.37.2</param>
+    <param name="revision">v8.37.4</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.oRRubM/_old  2025-06-10 09:07:53.125883963 +0200
+++ /var/tmp/diff_new_pack.oRRubM/_new  2025-06-10 09:07:53.157885285 +0200
@@ -1,7 +1,7 @@
 <servicedata>
   <service name="tar_scm">
     <param name="url">https://github.com/rqlite/rqlite.git</param>
-    <param 
name="changesrevision">5bc71b5eddecce7a4d542dbc022a0e9bcbda7aab</param>
+    <param 
name="changesrevision">4870c35c694f3173b83c45a275d7a943c8187535</param>
   </service>
 </servicedata>
 (No newline at EOF)

++++++ rqlite-8.37.2.tar.xz -> rqlite-8.37.4.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-8.37.2/CHANGELOG.md 
new/rqlite-8.37.4/CHANGELOG.md
--- old/rqlite-8.37.2/CHANGELOG.md      2025-05-30 21:14:32.000000000 +0200
+++ new/rqlite-8.37.4/CHANGELOG.md      2025-06-07 17:38:12.000000000 +0200
@@ -1,3 +1,11 @@
+## v8.37.4 (Jun 7th 2025)
+### Implementation changes and bug fixes
+- [PR #2098](https://github.com/rqlite/rqlite/pull/2098): Upgrade SQL parser.
+
+## v8.37.3 (Jun 6th 2025)
+### Implementation changes and bug fixes
+- [PR #2097](https://github.com/rqlite/rqlite/pull/2097): Upgrade SQL parser.
+
 ## v8.37.2 (May 30th 2025)
 ### Implementation changes and bug fixes
 - [PR #2092](https://github.com/rqlite/rqlite/pull/2092): Update Go module 
dependencies, Go version to 1.23.8, and toolchain to go1.23.9.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-8.37.2/go.mod new/rqlite-8.37.4/go.mod
--- old/rqlite-8.37.2/go.mod    2025-05-30 21:14:32.000000000 +0200
+++ new/rqlite-8.37.4/go.mod    2025-06-07 17:38:12.000000000 +0200
@@ -18,7 +18,7 @@
        github.com/rqlite/go-sqlite3 v1.38.0
        github.com/rqlite/raft-boltdb/v2 v2.0.0-20230523104317-c08e70f4de48
        github.com/rqlite/rqlite-disco-clients 
v0.0.0-20250205044118-8ada2b350099
-       github.com/rqlite/sql v0.0.0-20250530185618-c2b588be35aa
+       github.com/rqlite/sql v0.0.0-20250607152030-b0dd329faf9b
        go.etcd.io/bbolt v1.4.0
        golang.org/x/net v0.40.0
        google.golang.org/protobuf v1.36.6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-8.37.2/go.sum new/rqlite-8.37.4/go.sum
--- old/rqlite-8.37.2/go.sum    2025-05-30 21:14:32.000000000 +0200
+++ new/rqlite-8.37.4/go.sum    2025-06-07 17:38:12.000000000 +0200
@@ -235,8 +235,8 @@
 github.com/rqlite/raft-boltdb/v2 v2.0.0-20230523104317-c08e70f4de48/go.mod 
h1:CRnsxgy5G8fAf5J+AM0yrsSdxXHKkIYOaq2sm+Q4DYc=
 github.com/rqlite/rqlite-disco-clients v0.0.0-20250205044118-8ada2b350099 
h1:5cqkVLdl6sGJSY3kiF2dqaA3bD+8OS5FUdZqO0BxXLU=
 github.com/rqlite/rqlite-disco-clients 
v0.0.0-20250205044118-8ada2b350099/go.mod 
h1:6SVI8KegsW9Fyu2UQ+uvw0JI5CAILRYRyiQ/OFSJPrs=
-github.com/rqlite/sql v0.0.0-20250530185618-c2b588be35aa 
h1:EL+V1KDf6eVWJecvwvuUFPPo2tikHnw7QV5XTnw2NPQ=
-github.com/rqlite/sql v0.0.0-20250530185618-c2b588be35aa/go.mod 
h1:ib9zVtNgRKiGuoMyUqqL5aNpk+r+++YlyiVIkclVqPg=
+github.com/rqlite/sql v0.0.0-20250607152030-b0dd329faf9b 
h1:usSxlq+oR5Y8HZ6DTj04wLjc/17MFxYcslhFGHS41Lg=
+github.com/rqlite/sql v0.0.0-20250607152030-b0dd329faf9b/go.mod 
h1:ib9zVtNgRKiGuoMyUqqL5aNpk+r+++YlyiVIkclVqPg=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 
h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod 
h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sirupsen/logrus v1.2.0/go.mod 
h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=

++++++ vendor.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/rqlite/sql/README.md 
new/vendor/github.com/rqlite/sql/README.md
--- old/vendor/github.com/rqlite/sql/README.md  2025-05-30 21:14:32.000000000 
+0200
+++ new/vendor/github.com/rqlite/sql/README.md  2025-06-07 17:38:12.000000000 
+0200
@@ -1,7 +1,7 @@
 sql
 ===
 
-[![Circle 
CI](https://circleci.com/gh/rqlite/sql/tree/master.svg?style=svg)](https://circleci.com/gh/rqlite/sql/tree/master)
+[![Circle 
CI](https://circleci.com/gh/rqlite/sql/tree/master.svg?style=svg)](https://app.circleci.com/pipelines/github/rqlite/sql)
 
 This repository holds a pure Go SQL parser based on the 
[SQLite](https://sqlite.org/)
 SQL definition. It implements nearly all features of the language except 
`ATTACH`,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/rqlite/sql/ast.go 
new/vendor/github.com/rqlite/sql/ast.go
--- old/vendor/github.com/rqlite/sql/ast.go     2025-05-30 21:14:32.000000000 
+0200
+++ new/vendor/github.com/rqlite/sql/ast.go     2025-06-07 17:38:12.000000000 
+0200
@@ -11,104 +11,110 @@
        fmt.Stringer
 }
 
-func (*AlterTableStatement) node()        {}
-func (*AnalyzeStatement) node()           {}
-func (*ReindexStatement) node()           {}
-func (*Assignment) node()                 {}
-func (*BeginStatement) node()             {}
-func (*BinaryExpr) node()                 {}
-func (*BindExpr) node()                   {}
-func (*BlobLit) node()                    {}
-func (*BoolLit) node()                    {}
-func (*Call) node()                       {}
-func (*CaseBlock) node()                  {}
-func (*CaseExpr) node()                   {}
-func (*CastExpr) node()                   {}
-func (*CheckConstraint) node()            {}
-func (*CollateConstraint) node()          {}
-func (*ColumnDefinition) node()           {}
-func (*CommitStatement) node()            {}
-func (*CreateIndexStatement) node()       {}
-func (*CreateTableStatement) node()       {}
-func (*CreateTriggerStatement) node()     {}
-func (*CreateViewStatement) node()        {}
-func (*DefaultConstraint) node()          {}
-func (*DeleteStatement) node()            {}
-func (*DropIndexStatement) node()         {}
-func (*DropTableStatement) node()         {}
-func (*DropTriggerStatement) node()       {}
-func (*DropViewStatement) node()          {}
-func (*Exists) node()                     {}
-func (*ExplainStatement) node()           {}
-func (*ExprList) node()                   {}
-func (*FilterClause) node()               {}
-func (*ForeignKeyArg) node()              {}
-func (*ForeignKeyConstraint) node()       {}
-func (*FrameSpec) node()                  {}
-func (*GeneratedConstraint) node()        {}
-func (*Ident) node()                      {}
-func (*IndexedColumn) node()              {}
-func (*InsertStatement) node()            {}
-func (*JoinClause) node()                 {}
-func (*JoinOperator) node()               {}
-func (*NotNullConstraint) node()          {}
-func (*NullLit) node()                    {}
-func (*NumberLit) node()                  {}
-func (*OnConstraint) node()               {}
-func (*OrderingTerm) node()               {}
-func (*OverClause) node()                 {}
-func (*ParenExpr) node()                  {}
-func (*ParenSource) node()                {}
-func (*PrimaryKeyConstraint) node()       {}
-func (*QualifiedRef) node()               {}
-func (*QualifiedTableName) node()         {}
-func (*QualifiedTableFunctionName) node() {}
-func (*Raise) node()                      {}
-func (*Range) node()                      {}
-func (*ReleaseStatement) node()           {}
-func (*ResultColumn) node()               {}
-func (*ReturningClause) node()            {}
-func (*RollbackStatement) node()          {}
-func (*SavepointStatement) node()         {}
-func (*SelectStatement) node()            {}
-func (*StringLit) node()                  {}
-func (*TimestampLit) node()               {}
-func (*Type) node()                       {}
-func (*UnaryExpr) node()                  {}
-func (*UniqueConstraint) node()           {}
-func (*UpdateStatement) node()            {}
-func (*UpsertClause) node()               {}
-func (*UsingConstraint) node()            {}
-func (*Window) node()                     {}
-func (*WindowDefinition) node()           {}
-func (*WithClause) node()                 {}
+func (*AlterTableStatement) node()         {}
+func (*AnalyzeStatement) node()            {}
+func (*Assignment) node()                  {}
+func (*BeginStatement) node()              {}
+func (*BinaryExpr) node()                  {}
+func (*BindExpr) node()                    {}
+func (*BlobLit) node()                     {}
+func (*BoolLit) node()                     {}
+func (*Call) node()                        {}
+func (*CaseBlock) node()                   {}
+func (*CaseExpr) node()                    {}
+func (*CastExpr) node()                    {}
+func (*CheckConstraint) node()             {}
+func (*CollateConstraint) node()           {}
+func (*ColumnDefinition) node()            {}
+func (*CommitStatement) node()             {}
+func (*CreateIndexStatement) node()        {}
+func (*CreateTableStatement) node()        {}
+func (*CreateTriggerStatement) node()      {}
+func (*CreateViewStatement) node()         {}
+func (*CreateVirtualTableStatement) node() {}
+func (*DefaultConstraint) node()           {}
+func (*DeleteStatement) node()             {}
+func (*DropIndexStatement) node()          {}
+func (*DropTableStatement) node()          {}
+func (*DropTriggerStatement) node()        {}
+func (*DropViewStatement) node()           {}
+func (*Exists) node()                      {}
+func (*ExplainStatement) node()            {}
+func (*ExprList) node()                    {}
+func (*FilterClause) node()                {}
+func (*ForeignKeyArg) node()               {}
+func (*ForeignKeyConstraint) node()        {}
+func (*FrameSpec) node()                   {}
+func (*GeneratedConstraint) node()         {}
+func (*Ident) node()                       {}
+func (*IndexedColumn) node()               {}
+func (*InsertStatement) node()             {}
+func (*JoinClause) node()                  {}
+func (*JoinOperator) node()                {}
+func (*ModuleArgument) node()              {}
+func (*NotNullConstraint) node()           {}
+func (*Null) node()                        {}
+func (*NullLit) node()                     {}
+func (*NumberLit) node()                   {}
+func (*OnConstraint) node()                {}
+func (*OrderingTerm) node()                {}
+func (*OverClause) node()                  {}
+func (*ParenExpr) node()                   {}
+func (*ParenSource) node()                 {}
+func (*PragmaStatement) node()             {}
+func (*PrimaryKeyConstraint) node()        {}
+func (*QualifiedRef) node()                {}
+func (*QualifiedTableName) node()          {}
+func (*QualifiedTableFunctionName) node()  {}
+func (*Raise) node()                       {}
+func (*Range) node()                       {}
+func (*ReindexStatement) node()            {}
+func (*ReleaseStatement) node()            {}
+func (*ResultColumn) node()                {}
+func (*ReturningClause) node()             {}
+func (*RollbackStatement) node()           {}
+func (*SavepointStatement) node()          {}
+func (*SelectStatement) node()             {}
+func (*StringLit) node()                   {}
+func (*TimestampLit) node()                {}
+func (*Type) node()                        {}
+func (*UnaryExpr) node()                   {}
+func (*UniqueConstraint) node()            {}
+func (*UpdateStatement) node()             {}
+func (*UpsertClause) node()                {}
+func (*UsingConstraint) node()             {}
+func (*Window) node()                      {}
+func (*WindowDefinition) node()            {}
+func (*WithClause) node()                  {}
 
 type Statement interface {
        Node
        stmt()
 }
 
-func (*AlterTableStatement) stmt()    {}
-func (*AnalyzeStatement) stmt()       {}
-func (*ReindexStatement) stmt()       {}
-func (*BeginStatement) stmt()         {}
-func (*CommitStatement) stmt()        {}
-func (*CreateIndexStatement) stmt()   {}
-func (*CreateTableStatement) stmt()   {}
-func (*CreateTriggerStatement) stmt() {}
-func (*CreateViewStatement) stmt()    {}
-func (*DeleteStatement) stmt()        {}
-func (*DropIndexStatement) stmt()     {}
-func (*DropTableStatement) stmt()     {}
-func (*DropTriggerStatement) stmt()   {}
-func (*DropViewStatement) stmt()      {}
-func (*ExplainStatement) stmt()       {}
-func (*InsertStatement) stmt()        {}
-func (*ReleaseStatement) stmt()       {}
-func (*RollbackStatement) stmt()      {}
-func (*SavepointStatement) stmt()     {}
-func (*SelectStatement) stmt()        {}
-func (*UpdateStatement) stmt()        {}
+func (*AlterTableStatement) stmt()         {}
+func (*AnalyzeStatement) stmt()            {}
+func (*BeginStatement) stmt()              {}
+func (*CommitStatement) stmt()             {}
+func (*CreateIndexStatement) stmt()        {}
+func (*CreateTableStatement) stmt()        {}
+func (*CreateTriggerStatement) stmt()      {}
+func (*CreateViewStatement) stmt()         {}
+func (*CreateVirtualTableStatement) stmt() {}
+func (*DeleteStatement) stmt()             {}
+func (*DropIndexStatement) stmt()          {}
+func (*DropTableStatement) stmt()          {}
+func (*DropTriggerStatement) stmt()        {}
+func (*DropViewStatement) stmt()           {}
+func (*ExplainStatement) stmt()            {}
+func (*InsertStatement) stmt()             {}
+func (*PragmaStatement) stmt()             {}
+func (*ReindexStatement) stmt()            {}
+func (*ReleaseStatement) stmt()            {}
+func (*RollbackStatement) stmt()           {}
+func (*SavepointStatement) stmt()          {}
+func (*SelectStatement) stmt()             {}
+func (*UpdateStatement) stmt()             {}
 
 // CloneStatement returns a deep copy stmt.
 func CloneStatement(stmt Statement) Statement {
@@ -133,6 +139,8 @@
                return stmt.Clone()
        case *CreateViewStatement:
                return stmt.Clone()
+       case *CreateVirtualTableStatement:
+               return stmt.Clone()
        case *DeleteStatement:
                return stmt.Clone()
        case *DropIndexStatement:
@@ -145,8 +153,12 @@
                return stmt.Clone()
        case *ExplainStatement:
                return stmt.Clone()
+       case *PragmaStatement:
+               return stmt.Clone()
        case *InsertStatement:
                return stmt.Clone()
+       case *ReindexStatement:
+               return stmt.Clone()
        case *ReleaseStatement:
                return stmt.Clone()
        case *RollbackStatement:
@@ -200,6 +212,7 @@
 func (*CaseExpr) expr()     {}
 func (*CastExpr) expr()     {}
 func (*Exists) expr()       {}
+func (*Null) expr()         {}
 func (*ExprList) expr()     {}
 func (*Ident) expr()        {}
 func (*NullLit) expr()      {}
@@ -236,6 +249,8 @@
                return expr.Clone()
        case *Exists:
                return expr.Clone()
+       case *Null:
+               return expr.Clone()
        case *ExprList:
                return expr.Clone()
        case *Ident:
@@ -258,6 +273,8 @@
                return expr.Clone()
        case *UnaryExpr:
                return expr.Clone()
+       case SelectExpr:
+               return expr.Clone()
        default:
                panic(fmt.Sprintf("invalid expr type: %T", expr))
        }
@@ -344,6 +361,8 @@
                return src.Clone()
        case *QualifiedTableName:
                return src.Clone()
+       case *QualifiedTableFunctionName:
+               return src.Clone()
        case *SelectStatement:
                return src.Clone()
        default:
@@ -628,6 +647,7 @@
        If          Pos    // position of IF keyword (optional)
        IfNot       Pos    // position of NOT keyword (optional)
        IfNotExists Pos    // position of EXISTS keyword (optional)
+       Schema      *Ident // optional schema name
        Name        *Ident // table name
 
        Lparen      Pos                 // position of left paren of column list
@@ -649,6 +669,7 @@
                return s
        }
        other := *s
+       other.Schema = s.Schema.Clone()
        other.Name = s.Name.Clone()
        other.Columns = cloneColumnDefinitions(s.Columns)
        other.Constraints = cloneConstraints(s.Constraints)
@@ -664,6 +685,10 @@
                buf.WriteString(" IF NOT EXISTS")
        }
        buf.WriteString(" ")
+       if s.Schema != nil {
+               buf.WriteString(s.Schema.String())
+               buf.WriteString(".")
+       }
        buf.WriteString(s.Name.String())
 
        if s.Select != nil {
@@ -1225,6 +1250,112 @@
        return buf.String()
 }
 
+type CreateVirtualTableStatement struct {
+       Create      Pos // position of CREATE keyword
+       Virtual     Pos // position of VIRTUAL keyword
+       Table       Pos // position of TABLE keyword
+       If          Pos // position of IF keyword (optional)
+       IfNot       Pos // position of NOT keyword (optional)
+       IfNotExists Pos // position of EXISTS keyword (optional)
+
+       Schema *Ident // schema name (optional)
+       Dot    Pos    // position of DOT token (optional)
+       Name   *Ident // table name
+
+       Using      Pos    // position of USING
+       ModuleName *Ident // name of an object that implements the virtual table
+
+       Lparen    Pos               // position of left paren of module 
argument list (optional)
+       Arguments []*ModuleArgument // module argument list (optional)
+       Rparen    Pos               // position of right paren of module 
argument list (optional)
+
+}
+
+// Clone returns a deep copy of s.
+func (s *CreateVirtualTableStatement) Clone() *CreateVirtualTableStatement {
+       if s == nil {
+               return s
+       }
+       other := *s
+       other.Schema = s.Name.Clone()
+       other.Name = s.Name.Clone()
+       other.ModuleName = s.ModuleName.Clone()
+       other.Arguments = cloneModuleArguments(s.Arguments)
+       return &other
+}
+
+// String returns the string representation of the statement.
+func (s *CreateVirtualTableStatement) String() string {
+       var buf bytes.Buffer
+       buf.WriteString("CREATE VIRTUAL TABLE ")
+       if s.IfNotExists.IsValid() {
+               buf.WriteString("IF NOT EXISTS ")
+       }
+
+       if s.Schema != nil {
+               buf.WriteString(s.Schema.String())
+               buf.WriteString(".")
+       }
+       buf.WriteString(s.Name.String())
+
+       buf.WriteString(" USING ")
+       buf.WriteString(s.ModuleName.String())
+       if s.Lparen.IsValid() {
+               buf.WriteString(" (")
+               for i := range s.Arguments {
+                       if i != 0 {
+                               buf.WriteString(",")
+                       }
+                       buf.WriteString(s.Arguments[i].String())
+               }
+               buf.WriteString(")")
+       }
+       return buf.String()
+}
+
+type ModuleArgument struct {
+       Name    *Ident // argument name
+       Assign  Pos    // position of ASSIGN token (optional)
+       Literal Expr   // literal that is assigned to name (optional)
+       Type    *Type  // type of Name, if Assign is set then Type cant be 
(optional)
+}
+
+func (a *ModuleArgument) Clone() *ModuleArgument {
+       if a == nil {
+               return a
+       }
+       other := *a
+       other.Name = a.Name.Clone()
+       other.Literal = CloneExpr(a.Literal)
+       other.Type = a.Type.Clone()
+       return &other
+}
+
+func (a *ModuleArgument) String() string {
+       var buf bytes.Buffer
+
+       buf.WriteString(a.Name.String())
+       if a.Assign.IsValid() {
+               buf.WriteString("=")
+               buf.WriteString(a.Literal.String())
+       } else if a.Type != nil {
+               buf.WriteString(" ")
+               buf.WriteString(a.Type.String())
+       }
+
+       return buf.String()
+}
+func cloneModuleArguments(a []*ModuleArgument) []*ModuleArgument {
+       if a == nil {
+               return nil
+       }
+       other := make([]*ModuleArgument, len(a))
+       for i := range a {
+               other[i] = a[i].Clone()
+       }
+       return other
+}
+
 type AnalyzeStatement struct {
        Analyze Pos    // position of ANALYZE keyword
        Name    *Ident // table name
@@ -1556,6 +1687,8 @@
                return "-" + expr.X.String()
        case NOT:
                return "NOT " + expr.X.String()
+       case BITNOT:
+               return "~" + expr.X.String()
        default:
                panic(fmt.Sprintf("sql.UnaryExpr.String(): invalid op %s", 
expr.Op))
        }
@@ -1820,6 +1953,30 @@
        return fmt.Sprintf("EXISTS (%s)", expr.Select.String())
 }
 
+type Null struct {
+       X     Expr  // expression being checked for null
+       Op    Token // IS or NOT token
+       OpPos Pos   // position of NOT NULL postfix operation
+}
+
+// Clone returns a deep copy of expr.
+func (expr *Null) Clone() *Null {
+       if expr == nil {
+               return nil
+       }
+       other := *expr
+       other.X = CloneExpr(expr.X)
+       return &other
+}
+
+// String returns the string representation of the expression.
+func (expr *Null) String() string {
+       if expr.Op == ISNULL {
+               return "IS NULL"
+       }
+       return "NOT NULL"
+}
+
 type ExprList struct {
        Lparen Pos    // position of left paren
        Exprs  []Expr // list of expressions
@@ -3365,10 +3522,82 @@
 // String returns the string representation of the clause.
 func (c *JoinClause) String() string {
        var buf bytes.Buffer
-       fmt.Fprintf(&buf, "%s%s%s", c.X.String(), c.Operator.String(), 
c.Y.String())
-       if c.Constraint != nil {
-               fmt.Fprintf(&buf, " %s", c.Constraint.String())
+
+       // Print the left side
+       buf.WriteString(c.X.String())
+
+       // Print the operator
+       buf.WriteString(c.Operator.String())
+
+       // Handle the right side
+       if y, ok := c.Y.(*JoinClause); ok {
+               // Special case: right side is a JoinClause
+
+               // Check if the X of the nested JoinClause is also a JoinClause
+               if yx, ok := y.X.(*JoinClause); ok {
+                       // Handle the double-nested case
+
+                       // Print the first table of the inner JoinClause
+                       buf.WriteString(yx.X.String())
+
+                       // Add the constraint for the first join
+                       if c.Constraint != nil {
+                               fmt.Fprintf(&buf, " %s", c.Constraint.String())
+                       }
+
+                       // Print the operator of the inner JoinClause
+                       buf.WriteString(yx.Operator.String())
+
+                       // Print the second table of the inner JoinClause
+                       buf.WriteString(yx.Y.String())
+
+                       // Add the constraint for the inner JoinClause
+                       if yx.Constraint != nil {
+                               fmt.Fprintf(&buf, " %s", yx.Constraint.String())
+                       }
+
+                       // Print the operator of the outer JoinClause
+                       buf.WriteString(y.Operator.String())
+
+                       // Print the right side of the outer JoinClause
+                       buf.WriteString(y.Y.String())
+
+                       // Add the constraint for the outer JoinClause
+                       if y.Constraint != nil {
+                               fmt.Fprintf(&buf, " %s", y.Constraint.String())
+                       }
+               } else {
+                       // Handle the singly-nested case
+
+                       // Print the left side of the nested JoinClause
+                       buf.WriteString(y.X.String())
+
+                       // Add the constraint for the first join
+                       if c.Constraint != nil {
+                               fmt.Fprintf(&buf, " %s", c.Constraint.String())
+                       }
+
+                       // Print the operator of the nested JoinClause
+                       buf.WriteString(y.Operator.String())
+
+                       // Print the right side of the nested JoinClause
+                       buf.WriteString(y.Y.String())
+
+                       // Add the constraint for the nested JoinClause
+                       if y.Constraint != nil {
+                               fmt.Fprintf(&buf, " %s", y.Constraint.String())
+                       }
+               }
+       } else {
+               // Normal case: right side is not a JoinClause
+               buf.WriteString(c.Y.String())
+
+               // Add the constraint
+               if c.Constraint != nil {
+                       fmt.Fprintf(&buf, " %s", c.Constraint.String())
+               }
        }
+
        return buf.String()
 }
 
@@ -3694,3 +3923,36 @@
 
        return buf.String()
 }
+
+type PragmaStatement struct {
+       Pragma Pos    // position of PRAGMA keyword
+       Schema *Ident // name of schema (optional)
+       Dot    Pos    // position of DOT token (optional)
+       Expr   Expr   // can be Ident, Call or BinaryExpr
+}
+
+// Clone returns a deep copy of s.
+func (s *PragmaStatement) Clone() *PragmaStatement {
+       if s == nil {
+               return s
+       }
+
+       other := *s
+       other.Schema = s.Schema.Clone()
+       other.Expr = CloneExpr(s.Expr)
+       return &other
+}
+
+// String returns the string representation of the pragma statement.
+func (s *PragmaStatement) String() string {
+       var buf bytes.Buffer
+
+       buf.WriteString("PRAGMA ")
+       if s.Schema != nil {
+               buf.WriteString(s.Schema.String())
+               buf.WriteString(".")
+       }
+       buf.WriteString(s.Expr.String())
+
+       return buf.String()
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/rqlite/sql/parser.go 
new/vendor/github.com/rqlite/sql/parser.go
--- old/vendor/github.com/rqlite/sql/parser.go  2025-05-30 21:14:32.000000000 
+0200
+++ new/vendor/github.com/rqlite/sql/parser.go  2025-06-07 17:38:12.000000000 
+0200
@@ -91,6 +91,8 @@
 // parseStmt parses all statement types.
 func (p *Parser) parseNonExplainStatement() (Statement, error) {
        switch p.peek() {
+       case PRAGMA:
+               return p.parsePragmaStatement()
        case ANALYZE:
                return p.parseAnalyzeStatement()
        case REINDEX:
@@ -245,6 +247,8 @@
        switch p.peek() {
        case TABLE:
                return p.parseCreateTableStatement(pos)
+       case VIRTUAL:
+               return p.parseCreateVirtualTableStatement(pos)
        case VIEW:
                return p.parseCreateViewStatement(pos)
        case INDEX, UNIQUE:
@@ -298,10 +302,29 @@
                stmt.IfNotExists = pos
        }
 
-       if stmt.Name, err = p.parseIdent("table name"); err != nil {
+       // Parse the first identifier (either schema or table name)
+       firstIdent, err := p.parseIdent("table name")
+       if err != nil {
                return &stmt, err
        }
 
+       // Check if it's a schema.table format
+       if p.peek() == DOT {
+               // First identifier is the schema name
+               stmt.Schema = firstIdent
+
+               // Consume the dot
+               p.scan()
+
+               // Parse the table name
+               if stmt.Name, err = p.parseIdent("table name"); err != nil {
+                       return &stmt, err
+               }
+       } else {
+               // Just a table name without schema
+               stmt.Name = firstIdent
+       }
+
        // Parse either a column/constraint list or build table from "AS 
<select>".
        switch p.peek() {
        case LP:
@@ -380,7 +403,7 @@
                return &col, err
        }
 
-       if tok := p.peek(); tok == IDENT {
+       if tok := p.peek(); tok == IDENT || tok == NULL {
                if col.Type, err = p.parseType(); err != nil {
                        return &col, err
                }
@@ -844,6 +867,119 @@
        return &cons, nil
 }
 
+func (p *Parser) parseCreateVirtualTableStatement(createPos Pos) (_ 
*CreateVirtualTableStatement, err error) {
+       assert(p.peek() == VIRTUAL)
+
+       var stmt CreateVirtualTableStatement
+       stmt.Create = createPos
+       stmt.Virtual, _, _ = p.scan()
+       stmt.Table, _, _ = p.scan()
+
+       // Parse optional "IF NOT EXISTS".
+       if p.peek() == IF {
+               stmt.If, _, _ = p.scan()
+
+               pos, tok, _ := p.scan()
+               if tok != NOT {
+                       return &stmt, p.errorExpected(pos, tok, "NOT")
+               }
+               stmt.IfNot = pos
+
+               pos, tok, _ = p.scan()
+               if tok != EXISTS {
+                       return &stmt, p.errorExpected(pos, tok, "EXISTS")
+               }
+               stmt.IfNotExists = pos
+       }
+
+       ident, err := p.parseIdent("schema or table name")
+       if err != nil {
+               return &stmt, err
+       }
+       if p.peek() == DOT {
+               stmt.Schema = ident
+               stmt.Dot, _, _ = p.scan()
+               if stmt.Name, err = p.parseIdent("table name"); err != nil {
+                       return &stmt, err
+               }
+       } else {
+               stmt.Name = ident
+       }
+
+       pos, tok, _ := p.scan()
+       if tok != USING {
+               return &stmt, p.errorExpected(p.pos, p.tok, "USING")
+       }
+       stmt.Using = pos
+
+       if stmt.ModuleName, err = p.parseIdent("module name"); err != nil {
+               return &stmt, err
+       }
+       // Module arguments can be optional
+       if p.peek() != LP {
+               return &stmt, nil
+       }
+       stmt.Lparen, _, _ = p.scan()
+
+       if stmt.Arguments, err = p.parseModuleArguments(); err != nil {
+               return &stmt, err
+       }
+
+       if len(stmt.Arguments) == 0 {
+               return &stmt, p.errorExpected(p.pos, p.tok, "module arguments")
+       }
+
+       if p.peek() != RP {
+               return &stmt, p.errorExpected(p.pos, p.tok, "right paren")
+       }
+       stmt.Rparen, _, _ = p.scan()
+
+       return &stmt, nil
+}
+
+func (p *Parser) parseModuleArguments() (_ []*ModuleArgument, err error) {
+       var args []*ModuleArgument
+
+       for p.peek() != RP {
+               arg, err := p.parseModuleArgument()
+               if err != nil {
+                       return args, err
+               }
+               args = append(args, arg)
+
+               if p.peek() == COMMA {
+                       p.scan()
+               } else if p.peek() != RP {
+                       return args, p.errorExpected(p.pos, p.tok, "comma or 
right paren")
+               }
+       }
+
+       return args, nil
+}
+
+func (p *Parser) parseModuleArgument() (_ *ModuleArgument, err error) {
+       var arg ModuleArgument
+
+       if arg.Name, err = p.parseIdent("module argument name"); err != nil {
+               return &arg, err
+       }
+
+       if p.peek() == EQ {
+               // Parse literal
+               arg.Assign, _, _ = p.scan()
+               if arg.Literal, err = p.parseOperand(); err != nil {
+                       return &arg, err
+               }
+       } else if isTypeName(p.lit) {
+               if arg.Type, err = p.parseType(); err != nil {
+                       return &arg, err
+               }
+
+       }
+
+       return &arg, nil
+}
+
 func (p *Parser) parseDropTableStatement(dropPos Pos) (_ *DropTableStatement, 
err error) {
        assert(p.peek() == TABLE)
 
@@ -1217,6 +1353,8 @@
        switch tok {
        case IDENT, QIDENT:
                return &Ident{Name: lit, NamePos: pos, Quoted: tok == QIDENT}, 
nil
+       case NULL:
+               return &Ident{Name: lit, NamePos: pos}, nil
        default:
                if isBareToken(tok) {
                        return &Ident{Name: lit, NamePos: pos}, nil
@@ -1227,7 +1365,11 @@
 
 func (p *Parser) parseType() (_ *Type, err error) {
        var typ Type
-       for p.peek() == IDENT {
+       for {
+               tok := p.peek()
+               if tok != IDENT && tok != NULL {
+                       break
+               }
                typeName, err := p.parseIdent("type name")
                if err != nil {
                        return &typ, err
@@ -2139,8 +2281,7 @@
        }
        source.Rparen, _, _ = p.scan()
 
-       // Only parse aliases for nested select statements.
-       if _, ok := source.X.(*SelectStatement); ok && (p.peek() == AS || 
isIdentToken(p.peek())) {
+       if p.peek() == AS || isIdentToken(p.peek()) {
                if p.peek() == AS {
                        source.As, _, _ = p.scan()
                }
@@ -2367,7 +2508,7 @@
                return &BoolLit{ValuePos: pos, Value: tok == TRUE}, nil
        case tok == BIND:
                return &BindExpr{NamePos: pos, Name: lit}, nil
-       case tok == PLUS, tok == MINUS:
+       case tok == PLUS, tok == MINUS, tok == BITNOT:
                expr, err = p.parseOperand()
                if err != nil {
                        return nil, err
@@ -2423,7 +2564,10 @@
                }
 
                switch op {
+               case NOTNULL, ISNULL:
+                       x = &Null{X: x, OpPos: pos, Op: op}
                case IN, NOTIN:
+
                        y, err := p.parseExprList()
                        if err != nil {
                                return x, err
@@ -2838,14 +2982,42 @@
        return &spec, nil
 }
 
-func (p *Parser) parseParenExpr() (_ *ParenExpr, err error) {
-       var expr ParenExpr
-       expr.Lparen, _, _ = p.scan()
-       if expr.X, err = p.ParseExpr(); err != nil {
-               return &expr, err
+func (p *Parser) parseParenExpr() (Expr, error) {
+       lparen, _, _ := p.scan()
+
+       // Parse the first expression
+       x, err := p.ParseExpr()
+       if err != nil {
+               return nil, err
        }
-       expr.Rparen, _, _ = p.scan()
-       return &expr, nil
+
+       // If there's no comma after the first expression, treat it as a normal 
parenthesized expression
+       if p.peek() != COMMA {
+               rparen, _, _ := p.scan()
+               return &ParenExpr{Lparen: lparen, X: x, Rparen: rparen}, nil
+       }
+
+       // If there's a comma, we're dealing with an expression list
+       var list ExprList
+       list.Lparen = lparen
+       list.Exprs = append(list.Exprs, x)
+
+       for p.peek() == COMMA {
+               p.scan() // consume the comma
+
+               expr, err := p.ParseExpr()
+               if err != nil {
+                       return &list, err
+               }
+               list.Exprs = append(list.Exprs, expr)
+       }
+
+       if p.peek() != RP {
+               return &list, p.errorExpected(p.pos, p.tok, "right paren")
+       }
+       list.Rparen, _, _ = p.scan()
+
+       return &list, nil
 }
 
 func (p *Parser) parseCastExpr() (_ *CastExpr, err error) {
@@ -3092,6 +3264,54 @@
        }
 }
 
+func (p *Parser) parsePragmaStatement() (_ *PragmaStatement, err error) {
+       assert(p.peek() == PRAGMA)
+
+       var stmt PragmaStatement
+       stmt.Pragma, _, _ = p.scan()
+
+       lit, err := p.parseIdent("schema name")
+       if err != nil {
+               return &stmt, err
+       }
+
+       // Handle <schema>.<pragma-name>
+       if p.peek() == DOT {
+               stmt.Schema = lit
+               stmt.Dot, _, _ = p.scan()
+               if lit, err = p.parseIdent("pragma name"); err != nil {
+                       return &stmt, err
+               }
+       }
+
+       switch p.peek() {
+       case EQ:
+               // Parse as binary expression: pragma-name = value
+               opPos, _, _ := p.scan()
+               rhs, err := p.ParseExpr()
+               if err != nil {
+                       return &stmt, err
+               }
+               stmt.Expr = &BinaryExpr{
+                       X:     lit,
+                       OpPos: opPos,
+                       Op:    EQ,
+                       Y:     rhs,
+               }
+       case LP:
+               // Parse as function call: pragma-name(args)
+               call, err := p.parseCall(lit)
+               if err != nil {
+                       return &stmt, err
+               }
+               stmt.Expr = call
+       default:
+               stmt.Expr = lit
+       }
+
+       return &stmt, nil
+}
+
 func (p *Parser) parseAnalyzeStatement() (_ *AnalyzeStatement, err error) {
        assert(p.peek() == ANALYZE)
 
@@ -3154,6 +3374,9 @@
                if p.peek() == NOT {
                        p.scan()
                        return pos, ISNOT, nil
+               } else if p.peek() == NULL {
+                       p.scan()
+                       return pos, ISNULL, nil
                }
                return pos, IS, nil
        case NOT:
@@ -3176,8 +3399,11 @@
                case BETWEEN:
                        p.scan()
                        return pos, NOTBETWEEN, nil
+               case NULL:
+                       p.scan()
+                       return pos, NOTNULL, nil
                default:
-                       return pos, tok, p.errorExpected(p.pos, p.tok, "IN, 
LIKE, GLOB, REGEXP, MATCH, or BETWEEN")
+                       return pos, tok, p.errorExpected(p.pos, p.tok, "IN, 
LIKE, GLOB, REGEXP, MATCH, BETWEEN, IS/NOT NULL")
                }
        default:
                return pos, tok, nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/rqlite/sql/scanner.go 
new/vendor/github.com/rqlite/sql/scanner.go
--- old/vendor/github.com/rqlite/sql/scanner.go 2025-05-30 21:14:32.000000000 
+0200
+++ new/vendor/github.com/rqlite/sql/scanner.go 2025-06-07 17:38:12.000000000 
+0200
@@ -58,7 +58,7 @@
                                s.read()
                                return pos, NE, "!="
                        }
-                       return pos, BITNOT, "!"
+                       return pos, ILLEGAL, "!"
                case '=':
                        if s.peek() == '=' {
                                s.read()
@@ -119,6 +119,8 @@
                        return pos, SLASH, "/"
                case '%':
                        return pos, REM, "%"
+               case '~':
+                       return pos, BITNOT, "~"
                default:
                        return pos, ILLEGAL, string(ch)
                }
@@ -271,6 +273,25 @@
 
        s.buf.Reset()
 
+       if s.peek() == '0' {
+               s.buf.WriteRune('0')
+               s.read()
+               if s.peek() == 'x' || s.peek() == 'X' {
+                       s.read()
+                       s.buf.WriteRune('x')
+                       for isHex(s.peek()) {
+                               ch, _ := s.read()
+                               s.buf.WriteRune(ch)
+                       }
+                       // TODO: error handling:
+                       // if len(s.buf.String()) < 2 => invalid
+                       // reason: means we scanned '0x'
+                       // if len(s.buf.String()) - 2 > 16 => invalid
+                       // reason: according to spec maximum of 16 significant 
digits)
+                       return pos, tok, s.buf.String()
+               }
+       }
+
        // Read whole number if starting with a digit.
        if isDigit(s.peek()) {
                for isDigit(s.peek()) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/rqlite/sql/token.go 
new/vendor/github.com/rqlite/sql/token.go
--- old/vendor/github.com/rqlite/sql/token.go   2025-05-30 21:14:32.000000000 
+0200
+++ new/vendor/github.com/rqlite/sql/token.go   2025-06-07 17:38:12.000000000 
+0200
@@ -61,7 +61,7 @@
        GE     // >=
        BITAND // &
        BITOR  // |
-       BITNOT // !
+       BITNOT // ~
        LSHIFT // <<
        RSHIFT // >>
        PLUS   // +
@@ -278,7 +278,7 @@
        GE:     ">=",
        BITAND: "&",
        BITOR:  "|",
-       BITNOT: "!",
+       BITNOT: "~",
        LSHIFT: "<<",
        RSHIFT: ">>",
        PLUS:   "+",
@@ -524,8 +524,8 @@
        // List keywords that can be used as identifiers in expressions
        case ROWID, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP:
                return true
-       // replace() core function
-       case REPLACE:
+       // Core functions
+       case REPLACE, LIKE, GLOB, IF:
                return true
        // Add any other non-reserved keywords here
        default:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt
--- old/vendor/modules.txt      2025-05-30 21:14:32.000000000 +0200
+++ new/vendor/modules.txt      2025-06-07 17:38:12.000000000 +0200
@@ -233,7 +233,7 @@
 github.com/rqlite/rqlite-disco-clients/dnssrv
 github.com/rqlite/rqlite-disco-clients/etcd
 github.com/rqlite/rqlite-disco-clients/expand
-# github.com/rqlite/sql v0.0.0-20250530185618-c2b588be35aa
+# github.com/rqlite/sql v0.0.0-20250607152030-b0dd329faf9b
 ## explicit; go 1.17
 github.com/rqlite/sql
 # go.etcd.io/bbolt v1.4.0

Reply via email to