@@ -32,9 +32,73 @@ License: MIT License (see homepage)
32
32
33
33
// DB innards
34
34
DB = { } ,
35
- AFFECTED_ROWS = 0 ;
36
-
35
+ AFFECTED_ROWS = 0 ,
36
+
37
+ // The RESULT_SET object inherits from Array
38
+ RESULT_SET = function ( ) { } ;
39
+ RESULT_SET . prototype = Array . prototype ;
40
+ RESULT_SET . prototype . ORDER_BY = function ( order )
41
+ {
42
+ var
43
+ arr = this ,
44
+ l , key , sort ;
37
45
46
+ if ( order == 'RANDOM' )
47
+ {
48
+ arr . sort ( function ( ) {
49
+ return 0.5 - Math . random ( ) ;
50
+ } ) ;
51
+ }
52
+ else
53
+ {
54
+ // convert order to an array
55
+ order = order . split ( ',' ) ;
56
+ l = order . length ;
57
+ // loop in reverse order (to keep the specificity correct)
58
+ while ( l -- )
59
+ {
60
+ order [ l ] = order [ l ] . trim ( ) . split ( ' ' ) ;
61
+ key = order [ l ] [ 0 ] ;
62
+ sort = order [ l ] [ 1 ] ;
63
+ arr . sort ( function ( a , b ) {
64
+ var
65
+ ret = 0 ;
66
+ // work on copies
67
+ a = clone ( a ) ;
68
+ b = clone ( b ) ;
69
+ if ( typeof a [ key ] == 'string' )
70
+ {
71
+ a = a [ key ] . toLowerCase ( ) ;
72
+ b = b [ key ] . toLowerCase ( ) ;
73
+ if ( sort == 'ASC' )
74
+ {
75
+ ret = a < b ? - 1 : ( a > b ? 1 : 0 ) ;
76
+ }
77
+ else
78
+ {
79
+ ret = a < b ? 1 : ( a > b ? - 1 : 0 ) ;
80
+ }
81
+ }
82
+ if ( typeof a [ key ] == 'number' )
83
+ {
84
+ ret = sort == 'DESC' ? b [ key ] - a [ key ] : a [ key ] - b [ key ] ;
85
+ }
86
+ return ret ;
87
+ } ) ;
88
+ }
89
+ }
90
+ return arr ;
91
+ } ;
92
+ RESULT_SET . prototype . LIMIT = function ( start , end )
93
+ {
94
+ if ( ! end )
95
+ {
96
+ end = start ;
97
+ start = 0 ;
98
+ }
99
+ return this . splice ( start , end ) ;
100
+ } ;
101
+
38
102
/**
39
103
* init() -> undefined
40
104
* Initializes the DB and loads its contents in to memory
@@ -114,26 +178,45 @@ License: MIT License (see homepage)
114
178
* Finds items within the data set that match the supplied criteria
115
179
*
116
180
* @param array d - the data set
117
- * @param object c - the criteria to be matched
181
+ * @param mixed c - the criteria object to be matched or the criteria function
118
182
*/
119
183
function findMatches ( d , c )
120
184
{
121
185
var
186
+ d = clone ( d ) , // never let a select mutate a row
122
187
i = d . length ,
123
- a = [ ] ,
188
+ a = new RESULT_SET ( ) ,
124
189
r , p ;
125
- rows: while ( i -- )
190
+ if ( c instanceof Function )
126
191
{
127
- r = d [ i ] ;
128
- for ( p in c )
192
+ while ( i -- )
129
193
{
130
- if ( c . hasOwnProperty ( p ) &&
131
- r [ p ] != c [ p ] )
194
+ r = c ( d [ i ] ) ;
195
+ if ( ! ! r )
132
196
{
133
- continue rows;
197
+ a . push ( d [ i ] ) ;
198
+ }
199
+ }
200
+ }
201
+ else if ( c instanceof Object )
202
+ {
203
+ rows: while ( i -- )
204
+ {
205
+ r = d [ i ] ;
206
+ for ( p in c )
207
+ {
208
+ if ( c . hasOwnProperty ( p ) &&
209
+ r [ p ] != c [ p ] )
210
+ {
211
+ continue rows;
212
+ }
134
213
}
214
+ a . push ( r ) ;
135
215
}
136
- a . push ( r ) ;
216
+ }
217
+ else if ( ! c )
218
+ {
219
+ a = d . reverse ( ) ;
137
220
}
138
221
return a . reverse ( ) ;
139
222
}
@@ -173,6 +256,14 @@ License: MIT License (see homepage)
173
256
{
174
257
return writeToCache ( table , DB [ table ] ) ;
175
258
}
259
+ /**
260
+ * clone( obj ) -> object
261
+ * Clones a given object
262
+ */
263
+ function clone ( obj )
264
+ {
265
+ return decode ( encode ( obj ) ) ;
266
+ }
176
267
177
268
178
269
// ------------------------
@@ -207,6 +298,15 @@ License: MIT License (see homepage)
207
298
return AFFECTED_ROWS ;
208
299
} ;
209
300
301
+ /**
302
+ * LocalStorageDB.SHOW_TABLES() -> array
303
+ * Provides an array of table names
304
+ */
305
+ this . SHOW_TABLES = function ( )
306
+ {
307
+ return DB [ TABLES ] ;
308
+ } ;
309
+
210
310
/**
211
311
* LocalStorageDB.CREATE( table, proto, data ) -> boolean
212
312
* Creates a new table and (optionally) in serts data into it
@@ -392,10 +492,15 @@ License: MIT License (see homepage)
392
492
* LocalStorageDB.SELECT( table )
393
493
* @param str table - the table to read
394
494
*
395
- * Option 2: Select based on criteria
495
+ * Option 2: Select based on criteria object
396
496
* LocalStorageDB.SELECT( table, criteria )
397
497
* @param str table - the table to read
398
498
* @param obj criteria - the criteria to match
499
+ *
500
+ * Option 3: Select based on criteria function
501
+ * LocalStorageDB.SELECT( table, criteria )
502
+ * @param str table - the table to read
503
+ * @param function criteria - the function to run against each row
399
504
*/
400
505
this . SELECT = function ( table , criteria )
401
506
{
@@ -408,38 +513,74 @@ License: MIT License (see homepage)
408
513
throw new Error ( table + ' is not a valid table name' ) ;
409
514
}
410
515
} ;
411
-
516
+
517
+
412
518
/**
413
- * LocalStorageDB.UPDATE( table, data , criteria ) -> undefined
519
+ * LocalStorageDB.UPDATE( table, mutation , criteria ) -> undefined
414
520
* Updates data in the table
415
521
*
416
522
* Option 1: Update all rows
417
- * LocalStorageDB.UPDATE( table, data )
523
+ * LocalStorageDB.UPDATE( table, mutation )
418
524
* @param str table - the table to use
419
- * @param obj data - the data object to use for updating the table
525
+ * @param obj mutation - the data object to use for mutating the table
420
526
*
421
527
* Option 2: Update select rows
422
- * LocalStorageDB.UPDATE( table, data , criteria )
528
+ * LocalStorageDB.UPDATE( table, mutation , criteria )
423
529
* @param str table - the table to use
424
- * @param obj data - the data object to use for updating the table
530
+ * @param obj mutation - the data object to use for mutating the table
425
531
* @param obj criteria - the criteria to match
532
+ *
533
+ * Option 3: Custom mutation
534
+ * LocalStorageDB.UPDATE( table, mutation )
535
+ * @param str table - the table to use
536
+ * @param function mutation - a function for use in mutating the table
426
537
*/
427
- this . UPDATE = function ( table , data , criteria )
538
+ this . UPDATE = function ( table , mutation , criteria )
428
539
{
429
540
AFFECTED_ROWS = 0 ;
430
541
if ( tableExists ( table ) )
431
542
{
432
- if ( data instanceof Object )
543
+ if ( mutation instanceof Function )
544
+ {
545
+ var
546
+ i = DB [ table ] . data . length ,
547
+ o_data , n_data , p , changed ;
548
+ while ( i -- )
549
+ {
550
+ changed = false ;
551
+ o_data = DB [ table ] . data [ i ] ;
552
+ n_data = mutation ( clone ( o_data ) ) ; // clone before mutating
553
+ if ( ! ! n_data )
554
+ {
555
+ for ( p in o_data )
556
+ {
557
+ if ( o_data . hasOwnProperty ( p ) &&
558
+ o_data [ p ] != n_data [ p ] )
559
+ {
560
+ changed = true ;
561
+ break ;
562
+ }
563
+ }
564
+ if ( changed )
565
+ {
566
+ DB [ table ] . data [ i ] = n_data ;
567
+ AFFECTED_ROWS ++ ;
568
+ }
569
+ }
570
+ }
571
+ }
572
+ else if ( mutation instanceof Object )
433
573
{
434
574
withMatches ( DB [ table ] . data , criteria , function ( i ) {
435
575
var
436
576
newData = DB [ table ] . data [ i ] ,
437
577
p ;
438
- for ( p in data )
578
+ for ( p in DB [ table ] . dfn )
439
579
{
440
- if ( data . hasOwnProperty ( p ) )
580
+ if ( DB [ table ] . dfn . hasOwnProperty ( p ) &&
581
+ mutation . hasOwnProperty ( p ) )
441
582
{
442
- newData [ p ] = data [ p ] ;
583
+ newData [ p ] = mutation [ p ] ;
443
584
}
444
585
}
445
586
DB [ table ] . data [ i ] = newData ;
@@ -448,7 +589,7 @@ License: MIT License (see homepage)
448
589
}
449
590
else
450
591
{
451
- throw new Error ( 'LocalStorageDB.insert () expects an Object or an array of Objects to be inserted as data ' ) ;
592
+ throw new Error ( 'LocalStorageDB.UPDATE () expects a mutation object or function as the second argument ' ) ;
452
593
}
453
594
cache ( table ) ;
454
595
}
0 commit comments