@@ -22,12 +22,14 @@ enum AT {
2222 * When creating a new istance of the SQLiteManager class, the constructor:
2323 * - will get you in the alter table section if you pass an entire table
2424 * - will get you to the create table section if you just pass the name of the table or you pass nothing
25+ * IMPORTANT: if you don't call sqlite_schema before making any change, then old views, triggers and indexes will be lost
2526 *
2627 * */
2728export class SQLiteManager {
2829 private table : SQLiteManagerTable
2930 private create = false
3031 private query = ''
32+ private sql : string [ ] = [ ]
3133
3234 constructor ( table ?: SQLiteManagerTable ) {
3335 if ( typeof table === 'undefined' ) {
@@ -44,8 +46,9 @@ export class SQLiteManager {
4446 }
4547 }
4648
47- reset ( ) : void {
48- this . table = { } as SQLiteManagerTable
49+ /** Pass to this method the result of this query: SELECT sql FROM sqlite_schema WHERE tbl_name='X'; where X is the name of the table you're using */
50+ sqlite_schema ( sql : string [ ] ) : void {
51+ this . sql = sql
4952 }
5053
5154 /** If changing name in altertable you need to manually call the queryBuilder() */
@@ -98,8 +101,15 @@ export class SQLiteManager {
98101 }
99102 break
100103 case AT . DROP_COLUMN :
101- if ( this . isReferenced ( column ) || column . constraints ?. PRIMARY_KEY || column . constraints ?. UNIQUE ) {
102- query += this . queryBuilder ( '' , { } as SQLiteManagerColumn )
104+ if (
105+ this . is ( column , true ) ||
106+ column . constraints ?. PRIMARY_KEY ||
107+ column . constraints ?. UNIQUE ||
108+ this . sql ?. includes ( column . name ) ||
109+ this . is ( column , false , true )
110+ // can't check for generated columns and outside this table CHECK constraints
111+ ) {
112+ query += this . queryBuilder ( '' + AT [ op ] , column )
103113 } else {
104114 this . query += 'ALTER TABLE "' + this . table . name + '" DROP COLUMN "' + column . name + '";\n'
105115 }
@@ -110,10 +120,6 @@ export class SQLiteManager {
110120 default :
111121 this . query += '\n\nPRAGMA foreign_keys = OFF;\n'
112122 this . query += 'BEGIN TRANSACTION;\n'
113- /*
114- this.query += 'WITH indexntriggernview AS (SELECT type, sql FROM sqlite_schema WHERE tbl_name="' + this.table.name + '");\n'
115- DROP views, indexes and triggers
116- */
117123 this . create = true
118124 oldname = this . table . name
119125 if ( typeof this . findColumn ( 'new_' + this . table . name ) == 'undefined' ) {
@@ -128,10 +134,21 @@ export class SQLiteManager {
128134 this . query += 'ALTER TABLE "' + this . table . name + '" RENAME TO "' + oldname + '";\n'
129135 this . table . name = oldname
130136 this . query += 'CREATE INDEX '
131- /*
132- Reconstruct using CREATE INDEX, CREATE TRIGGER, and CREATE VIEW
133- If any views refer to table X in a way that is affected by the schema change, then drop those views using DROP VIEW and recreate them with whatever changes are necessary to accommodate the schema change using CREATE VIEW.
134- */
137+
138+ if ( this . sql ) {
139+ if ( op == 'DROP_COLUMN' && column ) {
140+ this . sql . forEach ( element => {
141+ if ( ! element . includes ( column . name ) ) {
142+ query += element + '\n'
143+ }
144+ } )
145+ } else {
146+ this . sql . forEach ( element => {
147+ query += element + '\n'
148+ } )
149+ }
150+ }
151+
135152 this . query += 'PRAGMA foreign_key_check("' + this . table . name + '");\n'
136153 this . query += 'COMMIT;\n'
137154 this . query += 'PRAGMA foreign_keys = ON;\n'
@@ -214,18 +231,11 @@ export class SQLiteManager {
214231 return query
215232 }
216233
217- private isReferenced ( column : SQLiteManagerColumn ) : boolean {
218- if ( this . table . columns ) {
219- for ( let i = 0 ; i < this . table . columns . length ; i ++ ) {
220- if ( this . table . columns [ i ] . constraints ?. ForeignKey ?. column == column . name ) {
221- return true
222- }
223- }
224- }
225- return false
226- }
227-
228- addColumn ( column : SQLiteManagerColumn ) : string {
234+ /**
235+ * column: the SQLiteManagerColumn you want to add to the table
236+ * sql[]: SELECT sql FROM sqlite_schema WHERE tbl_name='X'; where X is the name of the table you're using
237+ */
238+ addColumn ( column : SQLiteManagerColumn , sql : string [ ] ) : string {
229239 if ( this . table . columns ) {
230240 if ( typeof this . findColumn ( column . name ) == 'undefined' ) {
231241 this . table . columns . push ( column )
@@ -236,10 +246,15 @@ export class SQLiteManager {
236246 this . table . columns = [ column ]
237247 }
238248
249+ this . sqlite_schema ( sql )
239250 return this . queryBuilder ( AT . ADD_COLUMN , column )
240251 }
241252
242- deleteColumn ( name : string ) : string {
253+ /**
254+ * name: name of the column you want to delete
255+ * sql[]: SELECT sql FROM sqlite_schema WHERE tbl_name='X'; where X is the name of the table you're using
256+ */
257+ deleteColumn ( name : string , sql : string [ ] ) : string {
243258 let query = ''
244259 const i = this . findColumn ( name )
245260
@@ -253,6 +268,7 @@ export class SQLiteManager {
253268 }
254269 }
255270
271+ this . sqlite_schema ( sql )
256272 return query
257273 }
258274
@@ -270,24 +286,43 @@ export class SQLiteManager {
270286 return this . queryBuilder ( AT . RENAME_COLUMN , { name : oldColumnName } as SQLiteManagerColumn , newColumnName )
271287 }
272288
273- changeColumnType ( name : string , type : SQLiteManagerType ) : string {
274- const i = this . findColumn ( name )
289+ /**
290+ * name: name of the column you want to change the type of
291+ * type: the new type you want to give to the column
292+ * sql[]: SELECT sql FROM sqlite_schema WHERE tbl_name='X'; where X is the name of the table you're using
293+ */
294+ changeColumnType ( name : string , type : SQLiteManagerType , sql : string [ ] ) : string {
295+ return this . generalFun ( name , ( column : SQLiteManagerColumn ) => ( column . type = type ) , sql )
296+ }
275297
276- if ( typeof i != 'undefined' && this . table . columns ) {
277- this . table . columns [ i ] . type = type
278- }
298+ /**
299+ * name: name of the column you want to change constraints of
300+ * constraits: edited constraints you get from getConstraints()
301+ * sql[]: SELECT sql FROM sqlite_schema WHERE tbl_name='X'; where X is the name of the table you're using
302+ */
303+ changeColumnConstraints ( name : string , constraints : SQLiteManagerConstraints , sql : string [ ] ) : string {
304+ return this . generalFun ( name , ( column : SQLiteManagerColumn ) => ( column . constraints = constraints ) , sql )
305+ }
279306
280- return this . queryBuilder ( '' , { } as SQLiteManagerColumn )
307+ /** name: name of the column you want to get the constraints of */
308+ getConstraints ( name : string ) : SQLiteManagerConstraints | undefined {
309+ let rtconstraints
310+ this . generalFun ( name , ( column : SQLiteManagerColumn ) => ( rtconstraints = column . constraints ) )
311+ return rtconstraints
281312 }
282313
283- changeColumnConstraints ( name : string , constraints : SQLiteManagerConstraints ) : string {
314+ private generalFun ( name : string , fun : ( column : SQLiteManagerColumn ) => void , sql ?: string [ ] , qb1 ?: any , qb2 ?: SQLiteManagerColumn ) : string {
284315 const i = this . findColumn ( name )
285316
286317 if ( typeof i != 'undefined' && this . table . columns ) {
287- this . table . columns [ i ] . constraints = constraints
318+ fun ( this . table . columns [ i ] )
288319 }
289320
290- return this . queryBuilder ( '' , { } as SQLiteManagerColumn )
321+ if ( sql ) {
322+ this . sqlite_schema ( sql )
323+ }
324+
325+ return this . queryBuilder ( qb1 ? qb1 : '' , qb2 ? qb2 : ( { } as SQLiteManagerColumn ) )
291326 }
292327
293328 private findColumn ( name : string ) : number | undefined {
@@ -298,4 +333,18 @@ export class SQLiteManager {
298333 }
299334 }
300335 }
336+
337+ private is ( column : SQLiteManagerColumn , referenced ?: boolean , checked ?: boolean ) : boolean {
338+ if ( this . table . columns ) {
339+ for ( let i = 0 ; i < this . table . columns . length ; i ++ ) {
340+ if ( referenced && this . table . columns [ i ] . constraints ?. ForeignKey ?. column == column . name ) {
341+ return true
342+ }
343+ if ( checked && this . table . columns [ i ] . constraints ?. Check ?. includes ( column . name ) ) {
344+ return true
345+ }
346+ }
347+ }
348+ return false
349+ }
301350}
0 commit comments