schangxiang@126.com
2025-09-19 0821aa23eabe557c0d9ef5dbe6989c68be35d1fe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
114
115
116
117
118
119
120
121
122
123
124
125
126
"use strict";
 
const WritableTrackingBuffer = require('./tracking-buffer/writable-tracking-buffer');
 
const writeAllHeaders = require('./all-headers').writeToTrackingBuffer;
/*
  s2.2.6.8
 */
 
 
const OPERATION_TYPE = module.exports.OPERATION_TYPE = {
  TM_GET_DTC_ADDRESS: 0x00,
  TM_PROPAGATE_XACT: 0x01,
  TM_BEGIN_XACT: 0x05,
  TM_PROMOTE_XACT: 0x06,
  TM_COMMIT_XACT: 0x07,
  TM_ROLLBACK_XACT: 0x08,
  TM_SAVE_XACT: 0x09
};
const ISOLATION_LEVEL = module.exports.ISOLATION_LEVEL = {
  NO_CHANGE: 0x00,
  READ_UNCOMMITTED: 0x01,
  READ_COMMITTED: 0x02,
  REPEATABLE_READ: 0x03,
  SERIALIZABLE: 0x04,
  SNAPSHOT: 0x05
};
const isolationLevelByValue = {};
 
for (const name in ISOLATION_LEVEL) {
  const value = ISOLATION_LEVEL[name];
  isolationLevelByValue[value] = name;
}
 
class Transaction {
  constructor(name, isolationLevel) {
    this.name = name;
    this.isolationLevel = isolationLevel;
    this.outstandingRequestCount = 1;
  }
 
  beginPayload(txnDescriptor) {
    const buffer = new WritableTrackingBuffer(100, 'ucs2');
    writeAllHeaders(buffer, txnDescriptor, this.outstandingRequestCount);
    buffer.writeUShort(OPERATION_TYPE.TM_BEGIN_XACT);
    buffer.writeUInt8(this.isolationLevel);
    buffer.writeUInt8(this.name.length * 2);
    buffer.writeString(this.name, 'ucs2');
    return {
      data: buffer.data,
      toString: () => {
        return 'Begin Transaction: name=' + this.name + ', isolationLevel=' + isolationLevelByValue[this.isolationLevel];
      }
    };
  }
 
  commitPayload(txnDescriptor) {
    const buffer = new WritableTrackingBuffer(100, 'ascii');
    writeAllHeaders(buffer, txnDescriptor, this.outstandingRequestCount);
    buffer.writeUShort(OPERATION_TYPE.TM_COMMIT_XACT);
    buffer.writeUInt8(this.name.length * 2);
    buffer.writeString(this.name, 'ucs2'); // No fBeginXact flag, so no new transaction is started.
 
    buffer.writeUInt8(0);
    return {
      data: buffer.data,
      toString: () => {
        return 'Commit Transaction: name=' + this.name;
      }
    };
  }
 
  rollbackPayload(txnDescriptor) {
    const buffer = new WritableTrackingBuffer(100, 'ascii');
    writeAllHeaders(buffer, txnDescriptor, this.outstandingRequestCount);
    buffer.writeUShort(OPERATION_TYPE.TM_ROLLBACK_XACT);
    buffer.writeUInt8(this.name.length * 2);
    buffer.writeString(this.name, 'ucs2'); // No fBeginXact flag, so no new transaction is started.
 
    buffer.writeUInt8(0);
    return {
      data: buffer.data,
      toString: () => {
        return 'Rollback Transaction: name=' + this.name;
      }
    };
  }
 
  savePayload(txnDescriptor) {
    const buffer = new WritableTrackingBuffer(100, 'ascii');
    writeAllHeaders(buffer, txnDescriptor, this.outstandingRequestCount);
    buffer.writeUShort(OPERATION_TYPE.TM_SAVE_XACT);
    buffer.writeUInt8(this.name.length * 2);
    buffer.writeString(this.name, 'ucs2');
    return {
      data: buffer.data,
      toString: () => {
        return 'Save Transaction: name=' + this.name;
      }
    };
  }
 
  isolationLevelToTSQL() {
    switch (this.isolationLevel) {
      case ISOLATION_LEVEL.READ_UNCOMMITTED:
        return 'READ UNCOMMITTED';
 
      case ISOLATION_LEVEL.READ_COMMITTED:
        return 'READ COMMITTED';
 
      case ISOLATION_LEVEL.REPEATABLE_READ:
        return 'REPEATABLE READ';
 
      case ISOLATION_LEVEL.SERIALIZABLE:
        return 'SERIALIZABLE';
 
      case ISOLATION_LEVEL.SNAPSHOT:
        return 'SNAPSHOT';
    }
 
    return '';
  }
 
}
 
module.exports.Transaction = Transaction;