@@ -151,7 +151,11 @@ def sync_table(model):
151151
152152 cluster = get_cluster ()
153153
154- keyspace = cluster .metadata .keyspaces [ks_name ]
154+ try :
155+ keyspace = cluster .metadata .keyspaces [ks_name ]
156+ except KeyError :
157+ raise CQLEngineException ("Keyspace '{0}' for model {1} does not exist." .format (ks_name , model ))
158+
155159 tables = keyspace .tables
156160
157161 syncd_types = set ()
@@ -161,7 +165,6 @@ def sync_table(model):
161165 for udt in [u for u in udts if u not in syncd_types ]:
162166 _sync_type (ks_name , udt , syncd_types )
163167
164- # check for an existing column family
165168 if raw_cf_name not in tables :
166169 log .debug ("sync_table creating new table %s" , cf_name )
167170 qs = _get_create_table (model )
@@ -175,32 +178,35 @@ def sync_table(model):
175178 raise
176179 else :
177180 log .debug ("sync_table checking existing table %s" , cf_name )
178- # see if we're missing any columns
179181 table_meta = tables [raw_cf_name ]
180- field_names = _get_non_pk_field_names (tables [raw_cf_name ])
182+
183+ _validate_pk (model , table_meta )
184+
185+ table_columns = table_meta .columns
181186 model_fields = set ()
182- # # TODO: does this work with db_name??
183- for name , col in model ._columns .items ():
184- if col .primary_key or col .partition_key :
185- continue # we can't mess with the PK
186- model_fields .add (name )
187- if col .db_field_name in field_names :
188- col_meta = table_meta .columns [col .db_field_name ]
189187
188+ for model_name , col in model ._columns .items ():
189+ db_name = col .db_field_name
190+ model_fields .add (db_name )
191+ if db_name in table_columns :
192+ col_meta = table_columns [db_name ]
190193 if col_meta .cql_type != col .db_type :
191194 msg = 'Existing table {0} has column "{1}" with a type ({2}) differing from the model type ({3}).' \
192- ' Model should be updated.' .format (cf_name , col . db_field_name , col_meta .cql_type , col .db_type )
195+ ' Model should be updated.' .format (cf_name , db_name , col_meta .cql_type , col .db_type )
193196 warnings .warn (msg )
194197 log .warning (msg )
195- continue # skip columns already defined
196198
197- # add missing column using the column def
199+ continue
200+
201+ if col .primary_key or col .primary_key :
202+ raise CQLEngineException ("Cannot add primary key '{0}' (with db_field '{1}') to existing table {2}" .format (model_name , db_name , cf_name ))
203+
198204 query = "ALTER TABLE {0} add {1}" .format (cf_name , col .get_column_def ())
199205 execute (query )
200206
201- db_fields_not_in_model = model_fields .symmetric_difference (field_names )
207+ db_fields_not_in_model = model_fields .symmetric_difference (table_columns )
202208 if db_fields_not_in_model :
203- log .info ("Table %s has fields not referenced by model: %s" , cf_name , db_fields_not_in_model )
209+ log .info ("Table {0} has fields not referenced by model: {1}" . format ( cf_name , db_fields_not_in_model ) )
204210
205211 _update_options (model )
206212
@@ -221,6 +227,22 @@ def sync_table(model):
221227 execute (qs )
222228
223229
230+ def _validate_pk (model , table_meta ):
231+ model_partition = [c .db_field_name for c in model ._partition_keys .values ()]
232+ meta_partition = [c .name for c in table_meta .partition_key ]
233+ model_clustering = [c .db_field_name for c in model ._clustering_keys .values ()]
234+ meta_clustering = [c .name for c in table_meta .clustering_key ]
235+
236+ if model_partition != meta_partition or model_clustering != meta_clustering :
237+ def _pk_string (partition , clustering ):
238+ return "PRIMARY KEY (({0}){1})" .format (', ' .join (partition ), ', ' + ', ' .join (clustering ) if clustering else '' )
239+ raise CQLEngineException ("Model {0} PRIMARY KEY composition does not match existing table {1}. "
240+ "Model: {2}; Table: {3}. "
241+ "Update model or drop the table." .format (model , model .column_family_name (),
242+ _pk_string (model_partition , model_clustering ),
243+ _pk_string (meta_partition , meta_clustering )))
244+
245+
224246def sync_type (ks_name , type_model ):
225247 """
226248 Inspects the type_model and creates / updates the corresponding type.
@@ -339,13 +361,6 @@ def add_column(col):
339361 return ' ' .join (query_strings )
340362
341363
342- def _get_non_pk_field_names (table_meta ):
343- # returns all fields that aren't part of the PK
344- pk_names = set (col .name for col in table_meta .primary_key )
345- field_names = [name for name in table_meta .columns .keys () if name not in pk_names ]
346- return field_names
347-
348-
349364def _get_table_metadata (model ):
350365 # returns the table as provided by the native driver for a given model
351366 cluster = get_cluster ()
0 commit comments