SQLite

Check-in [5ee2594b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Minor cleanups to [8fbda563d2f5].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 5ee2594b657b96aea9e482a175820dcbacfa9298da45b38cf17f39ad076d3f7f
User & Date: stephan 2024-04-22 17:03:52
Context
2024-04-22
20:09
Add extra tests for aborting conflicts in the sessions module. (check-in: b4a6d326 user: dan tags: trunk)
17:03
Minor cleanups to [8fbda563d2f5]. (check-in: 5ee2594b user: stephan tags: trunk)
16:46
Extend the JS/WASM SEE build support by (A) filtering SEE-related bits out of the JS when not building with SEE and (B) accepting an optional key/textkey/hexkey option to the sqlite3.oo1.DB and subclass constructors to create/open SEE-encrypted databases with. Demonstrate SEE in the test app using the kvvfs. This obviates the changes made in [5c505ee8a7]. (check-in: 8fbda563 user: stephan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/wasm/api/sqlite3-api-oo1.js.

83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
     A map of sqlite3_vfs pointers to SQL code or a callback function
     to run when the DB constructor opens a database with the given
     VFS. In the latter case, the call signature is (theDbObject,sqlite3Namespace)
     and the callback is expected to throw on error.
  */
  const __vfsPostOpenSql = Object.create(null);


  /**
     Converts ArrayBuffer or Uint8Array ba into a string of hex
     digits.
  */
  const byteArrayToHex = function(ba){
    if( ba instanceof ArrayBuffer ){
      ba = new Uint8Array(ba);
    }
    const li = [];
    const digits = "0123456789abcdef";
    for( const d of ba ){
      li.push( digits[(d & 0xf0) >> 4], digits[d & 0x0f] );
    }
    return li.join('');
  };

//#if enable-see
  /**
     Internal helper to apply an SEE key to a just-opened
     database. Requires that db be-a DB object which has just been
     opened, opt be the options object processed by its ctor, and opt
     must have either the key, hexkey, or textkey properties, either
     as a string, an ArrayBuffer, or a Uint8Array.








>
















<







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
     A map of sqlite3_vfs pointers to SQL code or a callback function
     to run when the DB constructor opens a database with the given
     VFS. In the latter case, the call signature is (theDbObject,sqlite3Namespace)
     and the callback is expected to throw on error.
  */
  const __vfsPostOpenSql = Object.create(null);

//#if enable-see
  /**
     Converts ArrayBuffer or Uint8Array ba into a string of hex
     digits.
  */
  const byteArrayToHex = function(ba){
    if( ba instanceof ArrayBuffer ){
      ba = new Uint8Array(ba);
    }
    const li = [];
    const digits = "0123456789abcdef";
    for( const d of ba ){
      li.push( digits[(d & 0xf0) >> 4], digits[d & 0x0f] );
    }
    return li.join('');
  };


  /**
     Internal helper to apply an SEE key to a just-opened
     database. Requires that db be-a DB object which has just been
     opened, opt be the options object processed by its ctor, and opt
     must have either the key, hexkey, or textkey properties, either
     as a string, an ArrayBuffer, or a Uint8Array.

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
      keytype = 'hexkey';
      key = opt.hexkey;
      if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
        key = byteArrayToHex(key);
      }else if('string'!==typeof key){
        toss3("Invalid value for the 'hexkey' option. Expecting a string, ArrayBuffer, or Uint8Array.");
      }
      /* else assume it's valid hex codes */;
    }else{
      return;
    }
    let stmt;
    try{
      stmt = db.prepare("PRAGMA "+keytype+"="+util.sqlite3__wasm_qfmt_token(key, 1));
      stmt.step();







|







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
      keytype = 'hexkey';
      key = opt.hexkey;
      if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
        key = byteArrayToHex(key);
      }else if('string'!==typeof key){
        toss3("Invalid value for the 'hexkey' option. Expecting a string, ArrayBuffer, or Uint8Array.");
      }
      /* else assume it's valid hex codes */
    }else{
      return;
    }
    let stmt;
    try{
      stmt = db.prepare("PRAGMA "+keytype+"="+util.sqlite3__wasm_qfmt_token(key, 1));
      stmt.step();
381
382
383
384
385
386
387
388






389
390
391
392
393
394
395
     - `vfs`: the VFS fname

//#if enable-see
     And, for SEE-capable builds, optionally ONE of the following:

     - `key`, `hexkey`, or `textkey`: encryption key as a string,
       ArrayBuffer, or Uint8Array. These flags function as documented
       for the SEE pragmas of the same names.







     In non-SEE builds, these options are ignored. In SEE builds,
     `PRAGMA key/textkey/hexkey=X` is executed immediately after
     opening the db. If more than one of the options is provided,
     or any option has an invalid argument type, an exception is
     thrown.
//#endif enable-see







|
>
>
>
>
>
>







381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
     - `vfs`: the VFS fname

//#if enable-see
     And, for SEE-capable builds, optionally ONE of the following:

     - `key`, `hexkey`, or `textkey`: encryption key as a string,
       ArrayBuffer, or Uint8Array. These flags function as documented
       for the SEE pragmas of the same names. Using a byte array for
       `hexkey` is equivalent to the same series of hex codes in
       string form, so '666f6f' is equivalent to
       Uint8Array([0x66,0x6f,0x6f]). A `textkey` byte array is assumed
       to be UTF-8. A `key` string is transformed into a UTF-8 byte
       array, and a `key` byte array is transformed into a `hexkey`
       with the same bytes.

     In non-SEE builds, these options are ignored. In SEE builds,
     `PRAGMA key/textkey/hexkey=X` is executed immediately after
     opening the db. If more than one of the options is provided,
     or any option has an invalid argument type, an exception is
     thrown.
//#endif enable-see

Changes to ext/wasm/tester1.c-pp.js.

2609
2610
2611
2612
2613
2614
2615






2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
    .t({
      name: 'kvvfs with SEE encryption',
      predicate: ()=>(isUIThread()
                      || "Only available in main thread."),
      test: function(sqlite3){
        this.kvvfsUnlink();
        let db;






        try{
          db = new this.JDb({
            filename: this.kvvfsDbFile,
            key: 'foo'
          });
          db.exec([
            "create table t(a,b);",
            "insert into t(a,b) values(1,2),(3,4)"
          ]);
          db.close();
          let err;







>
>
>
>
>
>



|







2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
    .t({
      name: 'kvvfs with SEE encryption',
      predicate: ()=>(isUIThread()
                      || "Only available in main thread."),
      test: function(sqlite3){
        this.kvvfsUnlink();
        let db;
        const encOpt1 = 1
              ? {textkey: 'foo'}
              : {key: 'foo'};
        const encOpt2 = encOpt1.textkey
              ? encOpt1
              : {hexkey: new Uint8Array([0x66,0x6f,0x6f]/*==>"foo"*/)}
        try{
          db = new this.JDb({
            filename: this.kvvfsDbFile,
            ...encOpt1
          });
          db.exec([
            "create table t(a,b);",
            "insert into t(a,b) values(1,2),(3,4)"
          ]);
          db.close();
          let err;
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
          }
          T.assert(err,"Expecting an exception")
            .assert(sqlite3.capi.SQLITE_NOTADB==err.resultCode,
                    "Expecting NOTADB");
          db = new sqlite3.oo1.DB({
            filename: this.kvvfsDbFile,
            vfs: 'kvvfs',
            hexkey: new Uint8Array([0x66,0x6f,0x6f]) // equivalent: '666f6f'
          });
          T.assert( 4===db.selectValue('select sum(a) from t') );
        }finally{
          if( db ) db.close();
          this.kvvfsUnlink();
        }
      }







|







2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
          }
          T.assert(err,"Expecting an exception")
            .assert(sqlite3.capi.SQLITE_NOTADB==err.resultCode,
                    "Expecting NOTADB");
          db = new sqlite3.oo1.DB({
            filename: this.kvvfsDbFile,
            vfs: 'kvvfs',
            ...encOpt2
          });
          T.assert( 4===db.selectValue('select sum(a) from t') );
        }finally{
          if( db ) db.close();
          this.kvvfsUnlink();
        }
      }