Skip to content

Commit 182256c

Browse files
Copilotmathiasrw
andauthored
Support bitwise operations to fix #155 (#2305)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> Co-authored-by: Mathias Wulff <m@rawu.dk>
1 parent cd6680f commit 182256c

2 files changed

Lines changed: 152 additions & 1 deletion

File tree

src/50expression.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@
187187
}
188188
}
189189

190-
const toTypeNumberOps = new Set(['-', '*', '/', '%', '^']);
190+
const toTypeNumberOps = new Set(['-', '*', '/', '%', '^', '<<', '>>', '&', '|']);
191191
const toTypeStringOps = new Set(['||']);
192192
// Regex to detect identifiers that need bracket wrapping (spaces, dots, hyphens, square brackets)
193193
const re_needsBrackets = /[\s.\-\[\]]/;

test/test155-B.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
}
5+
6+
describe('Test 155-B - Binary operators (<<, >>, &, |, ^)', function () {
7+
const test = '155B';
8+
9+
before(function () {
10+
alasql('create database test' + test);
11+
alasql('use test' + test);
12+
});
13+
14+
after(function () {
15+
alasql('drop database test' + test);
16+
});
17+
18+
it('A) Left shift operator (<<)', function () {
19+
var res = [
20+
alasql('SELECT 8 << 2 as result')[0],
21+
alasql('SELECT 1 << 5 as result')[0],
22+
alasql('SELECT 16 << 1 as result')[0],
23+
];
24+
assert.deepEqual(res, [{result: 32}, {result: 32}, {result: 32}]);
25+
});
26+
27+
it('B) Right shift operator (>>)', function () {
28+
var res = [
29+
alasql('SELECT 32 >> 2 as result')[0],
30+
alasql('SELECT 16 >> 1 as result')[0],
31+
alasql('SELECT 100 >> 3 as result')[0],
32+
alasql('SELECT -8 >> 2 as result')[0],
33+
];
34+
assert.deepEqual(res, [{result: 8}, {result: 8}, {result: 12}, {result: -2}]);
35+
});
36+
37+
it('C) Bitwise AND operator (&)', function () {
38+
var res = [
39+
alasql('SELECT 5 & 3 as result')[0],
40+
alasql('SELECT 12 & 10 as result')[0],
41+
alasql('SELECT 15 & 7 as result')[0],
42+
alasql('SELECT 255 & 15 as result')[0],
43+
];
44+
assert.deepEqual(res, [{result: 1}, {result: 8}, {result: 7}, {result: 15}]);
45+
});
46+
47+
it('D) Bitwise OR operator (|)', function () {
48+
var res = [
49+
alasql('SELECT 5 | 3 as result')[0],
50+
alasql('SELECT 12 | 10 as result')[0],
51+
alasql('SELECT 8 | 4 as result')[0],
52+
alasql('SELECT 1 | 2 | 4 | 8 as result')[0],
53+
];
54+
assert.deepEqual(res, [{result: 7}, {result: 14}, {result: 12}, {result: 15}]);
55+
});
56+
57+
it('E) Bitwise XOR operator (^)', function () {
58+
var res = [
59+
alasql('SELECT 5 ^ 3 as result')[0],
60+
alasql('SELECT 12 ^ 10 as result')[0],
61+
alasql('SELECT 15 ^ 15 as result')[0],
62+
alasql('SELECT 5 ^ 3 ^ 3 as result')[0],
63+
];
64+
assert.deepEqual(res, [{result: 6}, {result: 6}, {result: 0}, {result: 5}]);
65+
});
66+
67+
it('F) Binary operators with table data', function () {
68+
alasql('CREATE TABLE bitops (a INT, b INT)');
69+
alasql('INSERT INTO bitops VALUES (8, 2), (5, 3), (12, 4)');
70+
71+
var res = alasql('SELECT a, b, a << b as left_shift FROM bitops');
72+
assert.deepEqual(res, [
73+
{a: 8, b: 2, left_shift: 32},
74+
{a: 5, b: 3, left_shift: 40},
75+
{a: 12, b: 4, left_shift: 192},
76+
]);
77+
78+
res = alasql('SELECT a, b, a >> b as right_shift FROM bitops');
79+
assert.deepEqual(res, [
80+
{a: 8, b: 2, right_shift: 2},
81+
{a: 5, b: 3, right_shift: 0},
82+
{a: 12, b: 4, right_shift: 0},
83+
]);
84+
85+
res = alasql('SELECT a, b, a & b as bitwise_and FROM bitops');
86+
assert.deepEqual(res, [
87+
{a: 8, b: 2, bitwise_and: 0},
88+
{a: 5, b: 3, bitwise_and: 1},
89+
{a: 12, b: 4, bitwise_and: 4},
90+
]);
91+
92+
res = alasql('SELECT a, b, a | b as bitwise_or FROM bitops');
93+
assert.deepEqual(res, [
94+
{a: 8, b: 2, bitwise_or: 10},
95+
{a: 5, b: 3, bitwise_or: 7},
96+
{a: 12, b: 4, bitwise_or: 12},
97+
]);
98+
99+
res = alasql('SELECT a, b, a ^ b as bitwise_xor FROM bitops');
100+
assert.deepEqual(res, [
101+
{a: 8, b: 2, bitwise_xor: 10},
102+
{a: 5, b: 3, bitwise_xor: 6},
103+
{a: 12, b: 4, bitwise_xor: 8},
104+
]);
105+
106+
alasql('DROP TABLE bitops');
107+
});
108+
109+
it('G) Complex expressions with multiple binary operators', function () {
110+
var res = [
111+
alasql('SELECT (5 | 3) & 6 as result')[0],
112+
alasql('SELECT 5 ^ 3 ^ 5 as result')[0],
113+
alasql('SELECT (8 << 2) >> 1 as result')[0],
114+
alasql('SELECT (12 & 10) | (5 ^ 3) as result')[0],
115+
];
116+
assert.deepEqual(res, [{result: 6}, {result: 3}, {result: 16}, {result: 14}]);
117+
});
118+
119+
it('H) Binary operators in WHERE clause', function () {
120+
alasql('CREATE TABLE flags (num INT)');
121+
alasql('INSERT INTO flags VALUES (1), (2), (3), (4), (5), (6), (7), (8)');
122+
123+
var res = alasql('SELECT num FROM flags WHERE (num & 1) = 1');
124+
assert.deepEqual(res, [{num: 1}, {num: 3}, {num: 5}, {num: 7}]);
125+
126+
res = alasql('SELECT num FROM flags WHERE (num & 2) = 2');
127+
assert.deepEqual(res, [{num: 2}, {num: 3}, {num: 6}, {num: 7}]);
128+
129+
alasql('DROP TABLE flags');
130+
});
131+
132+
it('I) Binary operators with NULL values', function () {
133+
var res = [
134+
alasql('SELECT NULL << 2 as result')[0],
135+
alasql('SELECT 5 & NULL as result')[0],
136+
alasql('SELECT NULL | NULL as result')[0],
137+
];
138+
assert.deepEqual(res, [{result: undefined}, {result: undefined}, {result: undefined}]);
139+
});
140+
141+
it('J) Binary operators with zero', function () {
142+
var res = [
143+
alasql('SELECT 5 & 0 as result')[0],
144+
alasql('SELECT 5 | 0 as result')[0],
145+
alasql('SELECT 5 ^ 0 as result')[0],
146+
alasql('SELECT 0 << 5 as result')[0],
147+
alasql('SELECT 0 >> 5 as result')[0],
148+
];
149+
assert.deepEqual(res, [{result: 0}, {result: 5}, {result: 5}, {result: 0}, {result: 0}]);
150+
});
151+
});

0 commit comments

Comments
 (0)