@@ -250,10 +250,62 @@ public function dropColumn($table, $column)
250250 . " DROP " . $ this ->db ->quoteColumnName ($ column );
251251 }
252252
253+ /**
254+ * @inheritdoc
255+ */
253256 public function renameColumn ($ table , $ oldName , $ newName )
254257 {
255258 return "ALTER TABLE " . $ this ->db ->quoteTableName ($ table )
256259 . " ALTER " . $ this ->db ->quoteColumnName ($ oldName )
257260 . " TO " . $ this ->db ->quoteColumnName ($ newName );
258261 }
262+
263+ /**
264+ * @inheritdoc
265+ */
266+ public function alterColumn ($ table , $ column , $ type )
267+ {
268+ $ schema = $ this ->db ->getSchema ();
269+ $ tableSchema = $ schema ->getTableSchema ($ table );
270+ $ columnSchema = $ tableSchema ->getColumn ($ column );
271+
272+ $ allowNullNewType = !preg_match ("/not +null/i " , $ type );
273+
274+ $ type = preg_replace ("/ +(not)? *null/i " , "" , $ type );
275+
276+ $ hasType = false ;
277+
278+ $ matches = [];
279+ if (isset ($ this ->typeMap [$ type ])) {
280+ $ hasType = true ;
281+ } elseif (preg_match ('/^(\w+)[\( ]/ ' , $ type , $ matches )) {
282+ if (isset ($ this ->typeMap [$ matches [1 ]])) {
283+ $ hasType = true ;
284+ }
285+ }
286+
287+ $ baseSql = 'ALTER TABLE ' . $ this ->db ->quoteTableName ($ table )
288+ . ' ALTER ' . $ this ->db ->quoteColumnName ($ column )
289+ . (($ hasType )? ' TYPE ' : ' ' ) . $ this ->getColumnType ($ type );
290+
291+ if ($ columnSchema ->allowNull == $ allowNullNewType ) {
292+ return $ baseSql ;
293+ } else {
294+ $ sql = 'EXECUTE BLOCK AS BEGIN '
295+ . ' EXECUTE STATEMENT ' . $ this ->db ->quoteValue ($ baseSql ) . '; '
296+ . ' UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = ' . ($ allowNullNewType ? 'NULL ' : '1 ' )
297+ . ' WHERE UPPER(RDB$FIELD_NAME) = UPPER( \'' . $ column . '\') AND UPPER(RDB$RELATION_NAME) = UPPER( \'' . $ table . '\'); ' ;
298+ /**
299+ * In any case (whichever option you choose), make sure that the column doesn't have any NULLs.
300+ * Firebird will not check it for you. Later when you backup the database, everything is fine,
301+ * but restore will fail as the NOT NULL column has NULLs in it. To be safe, each time you change from NULL to NOT NULL.
302+ */
303+ if (!$ allowNullNewType ) {
304+ $ sql .= ' UPDATE ' . $ this ->db ->quoteTableName ($ table ) . ' SET ' . $ this ->db ->quoteColumnName ($ column ) . ' = 0 '
305+ . ' WHERE ' . $ this ->db ->quoteColumnName ($ column ) . ' IS NULL; ' ;
306+ }
307+ $ sql .= ' END ' ;
308+ return $ sql ;
309+ }
310+ }
259311}
0 commit comments