=== modified file 'uc_attribute/uc_attribute.admin.inc'
--- uc_attribute/uc_attribute.admin.inc	2009-06-09 15:01:27 +0000
+++ uc_attribute/uc_attribute.admin.inc	2009-06-13 08:41:53 +0000
@@ -122,12 +122,8 @@ function uc_attribute_form($form_state, 
  * Submit function for uc_attribute_add_form().
  */
 function uc_attribute_form_submit($form, &$form_state) {
-  if (!empty($form_state['values']['aid'])) {
-    db_query("UPDATE {uc_attributes} SET name = '%s', label = '%s', ordering = %d, required = %d, display = %d, description = '%s' WHERE aid = %d", $form_state['values']['name'], $form_state['values']['label'], $form_state['values']['ordering'], $form_state['values']['required'], $form_state['values']['display'], $form_state['values']['description'], $form_state['values']['aid']);
-  }
-  else {
-    db_query("INSERT INTO {uc_attributes} (name, label, ordering, required, display, description) VALUES ('%s', '%s', %d, %d, %d, '%s')", $form_state['values']['name'], $form_state['values']['label'], $form_state['values']['ordering'], $form_state['values']['required'], $form_state['values']['display'], $form_state['values']['description']);
-  }
+  $attribute = (object) $form_state['values'];
+  uc_attribute_save($attribute);
 
   $form_state['redirect'] = 'admin/store/attributes';
 }
@@ -175,13 +171,7 @@ function uc_attribute_admin_settings() {
 
 function uc_attribute_delete_confirm_submit($form, &$form_state) {
   if ($form_state['values']['confirm']) {
-    db_query("DELETE FROM {uc_class_attribute_options} WHERE EXISTS (SELECT * FROM {uc_attribute_options} AS ao WHERE {uc_class_attribute_options}.oid = ao.oid AND ao.aid = %d)", $form_state['values']['aid']);
-    db_query("DELETE FROM {uc_class_attributes} WHERE aid = %d", $form_state['values']['aid']);
-    db_query("DELETE FROM {uc_product_options} WHERE EXISTS (SELECT * FROM {uc_attribute_options} AS ao WHERE {uc_product_options}.oid = ao.oid AND ao.aid = %d)", $form_state['values']['aid']);
-    db_query("DELETE FROM {uc_product_adjustments} WHERE EXISTS (SELECT * FROM {uc_product_attributes} AS pa WHERE {uc_product_adjustments}.nid = pa.nid AND pa.aid = %d)", $form_state['values']['aid']);
-    db_query("DELETE FROM {uc_product_attributes} WHERE aid = %d", $form_state['values']['aid']);
-    db_query("DELETE FROM {uc_attribute_options} WHERE aid = %d", $form_state['values']['aid']);
-    db_query("DELETE FROM {uc_attributes} WHERE aid = %d", $form_state['values']['aid']);
+    uc_attribute_delete($form_state['values']['aid']);
     drupal_set_message(t('Product attribute deleted.'));
   }
 }
@@ -403,19 +393,18 @@ function uc_attribute_option_form_valida
  * Submit function for uc_attribute_option_form().
  */
 function uc_attribute_option_form_submit($form, &$form_state) {
-  if (!isset($form_state['values']['oid'])) {
-    db_query("INSERT INTO {uc_attribute_options} (aid, name, cost, price, weight, ordering) VALUES (%d, '%s', %f, %f, %f, %d)",
-      $form_state['values']['aid'], $form_state['values']['name'], $form_state['values']['cost'], $form_state['values']['price'], $form_state['values']['weight'], $form_state['values']['ordering']);
-    drupal_set_message(t('Created new option %option.', array('%option' => $form_state['values']['name'])));
-    watchdog('uc_attribute', 'Created new option %option.', array('%option' => $form_state['values']['name']), WATCHDOG_NOTICE, 'admin/store/attributes/'. $form_state['values']['aid'] .'/options/add');
-    $form_state['redirect'] = 'admin/store/attributes/'. $form_state['values']['aid'] .'/options/add';
-  }
-  else {
-    db_query("UPDATE {uc_attribute_options} SET name = '%s', cost = %f, price = %f, weight = %f, ordering = %d WHERE aid = %d AND oid = %d",
-      $form_state['values']['name'], $form_state['values']['cost'], $form_state['values']['price'], $form_state['values']['weight'], $form_state['values']['ordering'], $form_state['values']['aid'], $form_state['values']['oid']);
-    drupal_set_message(t('Updated option %option.', array('%option' => $form_state['values']['name'])));
-    watchdog('uc_attribute', 'Updated option %option.', array('%option' => $form_state['values']['name']), WATCHDOG_NOTICE, 'admin/store/attributes/'. $form_state['values']['aid'] .'/options/'. $form_state['values']['oid']);
-    $form_state['redirect'] = 'admin/store/attributes/'. $form_state['values']['aid'] .'/options';
+  $option = (object) $form_state['values'];
+  $op = uc_attribute_option_save($option);
+  
+  if ($op == SAVED_NEW) {
+    drupal_set_message(t('Created new option %option.', array('%option' => $option->name)));
+    watchdog('uc_attribute', 'Created new option %option.', array('%option' => $option->name), WATCHDOG_NOTICE, 'admin/store/attributes/'. $option->aid .'/options/add');
+    $form_state['redirect'] = 'admin/store/attributes/'. $option->aid .'/options/add';
+  }
+  elseif ($op == SAVED_UPDATED) {
+    drupal_set_message(t('Updated option %option.', array('%option' => $option->name)));
+    watchdog('uc_attribute', 'Updated option %option.', array('%option' => $option->name), WATCHDOG_NOTICE, 'admin/store/attributes/'. $option->aid .'/options/'. $option->od);
+    $form_state['redirect'] = 'admin/store/attributes/'. $option->aid .'/options';
   }
 }
 
@@ -443,9 +432,7 @@ function uc_attribute_option_delete_conf
  */
 function uc_attribute_option_delete_confirm_submit($form, &$form_state) {
   if ($form_state['values']['confirm']) {
-    $match = 'i:'. $form_state['values']['aid'] .';s:'. strlen($form_state['values']['oid']) .':"'. $form_state['values']['oid'] .'";';
-    db_query("DELETE FROM {uc_product_adjustments} WHERE combination LIKE '%%%s%%'", $match);
-    db_query("DELETE ao, co, po FROM {uc_attribute_options} AS ao LEFT JOIN {uc_product_options} AS po ON ao.oid = po.oid LEFT JOIN {uc_class_attribute_options} AS co ON ao.oid = co.oid WHERE ao.oid = %d", $form_state['values']['oid']);
+    uc_attribute_option_delete($form_state['values']['oid']);
   }
   $form_state['redirect'] = 'admin/store/attributes/'. $form_state['values']['aid'] .'/options';
 }
@@ -460,7 +447,6 @@ function uc_object_attributes_form($form
         drupal_goto('admin/store/products/classes/'. $id);
       }
       drupal_set_title(check_plain($class->name));
-      $attributes = uc_class_get_attributes($id);
       break;
     case 'product':
     default:
@@ -470,8 +456,8 @@ function uc_object_attributes_form($form
         drupal_goto('node/'. $id);
       }
       drupal_set_title(check_plain($product->title));
-      $attributes = uc_product_get_attributes($id);
   }
+  $attributes = uc_attribute_load_multiple(array(), $type, $id);
 
   $used_aids = array();
   $used_labels = array();
@@ -499,6 +485,10 @@ function uc_object_attributes_form($form
         );
 
         $form['attributes'][$attribute->aid] = array(
+          'aid' => array(
+            '#type' => 'hidden',
+            '#default_value' => $attribute->aid,
+          ),
           'remove' => array(
             '#type' => 'checkbox',
             '#default_value' => 0,
@@ -623,78 +613,59 @@ function theme_uc_object_attributes_form
   return $output;
 }
 
+/**
+ * Submit handler for the product/class attributes form.
+ */
 function uc_object_attributes_form_submit($form, &$form_state) {
-  if ($form_state['values']['type'] == 'product') {
-    $attr_table = '{uc_product_attributes}';
-    $opt_table = '{uc_product_options}';
-    $id = 'nid';
-    $sql_type = '%d';
-  }
-  elseif ($form_state['values']['type'] == 'class') {
-    $attr_table = '{uc_class_attributes}';
-    $opt_table = '{uc_class_attribute_options}';
-    $id = 'pcid';
-    $sql_type = "'%s'";
-  }
+  $type = $form_state['values']['type'];
+  $id = $form_state['values']['id'];
 
+  // The attribute edit form.
   if ($form_state['values']['view'] == 'overview' && is_array($form_state['values']['attributes'])) {
+    $remove_count = 0;
+
     foreach ($form_state['values']['attributes'] as $aid => $attribute) {
+      // Remove was checked.
       if ($attribute['remove']) {
-        $remove_aids[] = $aid;
+        uc_attribute_subject_delete($aid, $type, $id);
+        $remove_count++;
       }
+      // Update the attribute.
       else {
-        db_query("UPDATE $attr_table SET label = '%s', ordering = %d, required = %d, display = %d WHERE aid = %d AND $id = $sql_type", $attribute['label'], $attribute['ordering'], $attribute['required'], $attribute['display'], $aid, $form_state['values']['id']);
+        $attribute = (object) $attribute;
+        uc_attribute_subject_save($attribute, $type, $id);
+        
         $changed = TRUE;
       }
     }
 
-    if (count($remove_aids) > 0) {
-      $id_value = $form_state['values']['id'];
-      $remove_aids_value = implode(', ', $remove_aids);
-
-      db_query("DELETE FROM $opt_table WHERE EXISTS (SELECT * FROM {uc_attribute_options} AS ao WHERE $opt_table.oid = ao.oid AND ao.aid IN (%s)) AND $opt_table.$id = $sql_type", $remove_aids_value, $id_value);
-      db_query("DELETE FROM $attr_table WHERE $id = $sql_type AND aid IN (%s)", $id_value, $remove_aids_value);
-      if ($form_state['values']['type'] == 'product') {
-        db_query("DELETE FROM {uc_product_adjustments} WHERE nid = %d", $id_value);
-      }
-
-      drupal_set_message(format_plural(count($remove_aids), '@count attribute has been removed.', '@count attributes have been removed.'));
+    if ($remove_count) {
+      drupal_set_message(format_plural($remove_count, '@count attribute has been removed.', '@count attributes have been removed.'));
     }
 
     if ($changed) {
       drupal_set_message(t('The changes have been saved.'));
     }
   }
+  
+  // The attribute add form.
   elseif ($form_state['values']['view'] == 'add') {
     foreach ($form_state['values']['add_attributes'] as $aid) {
-      // Enable all options for added attributes.
+      // Load the base attribute, and save it with all its options.
       $attribute = uc_attribute_load($aid);
-      foreach ($attribute->options as $option) {
-        db_query("INSERT INTO $opt_table ($id, oid, cost, price, weight, ordering) VALUES ($sql_type, %d, %f, %f, %f, %d)", $form_state['values']['id'], $option->oid, $option->cost, $option->price, $option->weight, $option->ordering);
-      }
-      // Make the first option (if any) the default.
-      $option = reset($attribute->options);
-      if ($option) {
-        $oid = $option->oid;
-      }
-      else {
-        $oid = 0;
-      }
-      db_query("INSERT INTO $attr_table ($id, aid, label, ordering, default_option, required, display) SELECT $sql_type, aid, label, ordering, %d, required, display FROM {uc_attributes} WHERE aid = %d", $form_state['values']['id'], $oid, $aid);
+      uc_attribute_subject_save($attribute, $type, $id, TRUE);
     }
+
     if (count($form_state['values']['add_attributes']) > 0) {
-      if ($form_state['values']['type'] == 'product') {
-        db_query("DELETE FROM {uc_product_adjustments} WHERE nid = %d", $form_state['values']['id']);
-      }
       drupal_set_message(format_plural(count($form_state['values']['add_attributes']), '@count attribute has been added.', '@count attributes have been added.'));
     }
   }
 
   if ($form_state['values']['type'] == 'product') {
-    $form_state['redirect'] = 'node/'. $form_state['values']['id'] .'/edit/attributes';
+    $form_state['redirect'] = 'node/'. $id .'/edit/attributes';
   }
   else {
-    $form_state['redirect'] = 'admin/store/products/classes/'. $form_state['values']['id'] .'/attributes';
+    $form_state['redirect'] = 'admin/store/products/classes/'. $id .'/attributes';
   }
 }
 
@@ -704,7 +675,6 @@ function uc_object_options_form($form_st
     $product = $object;
     $id = $product->nid;
     drupal_set_title(check_plain($product->title));
-    $attributes = uc_product_get_attributes($id);
     $table = '{uc_product_options}';
     $id_type = 'nid';
     $sql_type = db_type_placeholder('int');
@@ -713,11 +683,12 @@ function uc_object_options_form($form_st
     $class = $object;
     $id = $class->pcid;
     drupal_set_title(check_plain($class->name));
-    $attributes = uc_class_get_attributes($id);
     $table = '{uc_class_attribute_options}';
     $id_type = 'pcid';
     $sql_type = db_type_placeholder('varchar');
   }
+  
+  $attributes = uc_attribute_load_multiple(array(), $type, $id);
 
   foreach ($attributes as $aid => $attribute) {
     $form['attributes'][$aid]['name'] = array(
@@ -771,7 +742,7 @@ function uc_object_options_form($form_st
         );
       }
 
-      $form['attributes'][$aid]['default'] = array(
+      $form['attributes'][$aid]['default_option'] = array(
         '#type' => 'radios',
         '#options' => $options,
         '#default_value' => /* $attribute->required ? NULL : */ $attribute->default_option,
@@ -779,7 +750,7 @@ function uc_object_options_form($form_st
       );
     }
     else {
-      $form['attributes'][$aid]['default'] = array(
+      $form['attributes'][$aid]['default_option'] = array(
         '#value' => t('This attribute does not have any options.'),
       );
     }
@@ -820,12 +791,11 @@ function theme_uc_object_options_form($f
 
     $rows = array();
 
-    if (element_children($form['attributes'][$key]['default'])) {
-
-      foreach (element_children($form['attributes'][$key]['default']) as $oid) {
+    if (element_children($form['attributes'][$key]['default_option'])) {
+      foreach (element_children($form['attributes'][$key]['default_option']) as $oid) {
         $row = array(
           drupal_render($form['attributes'][$key]['options'][$oid]['select']),
-          drupal_render($form['attributes'][$key]['default'][$oid]),
+          drupal_render($form['attributes'][$key]['default_option'][$oid]),
           drupal_render($form['attributes'][$key]['options'][$oid]['cost']),
           drupal_render($form['attributes'][$key]['options'][$oid]['price']),
           drupal_render($form['attributes'][$key]['options'][$oid]['weight']),
@@ -842,7 +812,7 @@ function theme_uc_object_options_form($f
     }
     else {
       $row = array();
-      $row[] = array('data' => drupal_render($form['attributes'][$key]['default']), 'colspan' => 6);
+      $row[] = array('data' => drupal_render($form['attributes'][$key]['default_option']), 'colspan' => 6);
       $rows[] = $row;
     }
 
@@ -883,8 +853,8 @@ function uc_object_options_form_validate
           }
         }
       }
-      if (!empty($selected_opts) && !$form['attributes'][$aid]['default']['#disabled'] && !in_array($attribute['default'], $selected_opts)) {
-        form_set_error($attribute['default']);
+      if (!empty($selected_opts) && !$form['attributes'][$aid]['default_option']['#disabled'] && !in_array($attribute['default_option'], $selected_opts)) {
+        form_set_error($attribute['default_option']);
         $error = TRUE;
       }
     }
@@ -895,41 +865,36 @@ function uc_object_options_form_validate
   }
 }
 
+/**
+ * Submit handler for the product/class attribute options form.
+ */
 function uc_object_options_form_submit($form, &$form_state) {
-  if ($form_state['values']['type'] == 'product') {
-    $attr_table = '{uc_product_attributes}';
-    $opt_table = '{uc_product_options}';
-    $id = 'nid';
-    $sql_type = '%d';
-  }
-  elseif ($form_state['values']['type'] == 'class') {
-    $attr_table = '{uc_class_attributes}';
-    $opt_table = '{uc_class_attribute_options}';
-    $id = 'pcid';
-    $sql_type = "'%s'";
-  }
+  $id = $form_state['values']['id'];
+  $type = $form_state['values']['type'];
 
   foreach ($form_state['values']['attributes'] as $attribute) {
-    db_query("UPDATE $attr_table SET default_option = %d WHERE $id = $sql_type AND aid = %d", $attribute['default'], $form_state['values']['id'], $attribute['aid']);
-
-    if (is_array($attribute['options'])) {
-      foreach ($attribute['options'] as $oid => $option) {
-        db_query("DELETE FROM $opt_table WHERE $id = $sql_type AND oid = %d", $form_state['values']['id'], $oid);
-
+    // Save the default option.
+    $attribute = (object) $attribute;
+    uc_attribute_subject_save($attribute, $type, $id);
+
+    // Deal with options if they exist.
+    if (is_array($attribute->options)) {
+      foreach ($attribute->options as $oid => $option) {
+        // Checked?
         if ($option['select']) {
-          db_query("INSERT INTO $opt_table ($id, oid, cost, price, weight, ordering) VALUES ($sql_type, %d, %f, %f, %f, %d)",
-                   $form_state['values']['id'], $oid, $option['cost'], $option['price'], $option['weight'], $option['ordering']);
+          $option = (object) $option;
+          $option->oid = $oid;
+          uc_attribute_subject_option_save($option, $type, $id);
         }
-        elseif ($form_state['values']['type'] == 'product') {
-          $aid = $attribute['aid'];
-          $match = 'i:'. $aid .';s:'. strlen($oid) .':"'. $oid .'";';
-          db_query("DELETE FROM {uc_product_adjustments} WHERE nid = %d AND combination LIKE '%%%s%%'", $form_state['values']['id'], $match);
+        // Unchecked means delete the option.
+        else {
+          uc_attribute_subject_option_delete($oid, $type, $id);
         }
       }
     }
   }
 
-  drupal_set_message(t('The !type options have been saved.', array('!type' => $form_state['values']['type'] == 'product' ? t('product') : t('product class'))));
+  drupal_set_message(t('The !type options have been saved.', array('!type' => $type == 'product' ? t('product') : t('product class'))));
 }
 
 /**

=== modified file 'uc_attribute/uc_attribute.module'
--- uc_attribute/uc_attribute.module	2009-06-10 20:28:03 +0000
+++ uc_attribute/uc_attribute.module	2009-06-15 05:34:04 +0000
@@ -293,7 +293,7 @@ function uc_attribute_nodeapi(&$node, $o
   if (uc_product_is_product($node->type)) {
     switch ($op) {
       case 'load':
-        $attributes = uc_product_get_attributes($node->nid);
+        $attributes = uc_attribute_load_product_attributes($node->nid);
         if (is_array($attributes) && !empty($attributes)) {
           $node->attributes = $attributes;
           return array('attributes' => $attributes);
@@ -320,7 +320,7 @@ function uc_attribute_nodeapi(&$node, $o
         break;
       case 'update index':
         $output = '';
-        $attributes = uc_product_get_attributes($node->nid);
+        $attributes = uc_attribute_load_product_attributes($node->nid);
         foreach ($attributes as $attribute) {
           $output .= '<h3>'. _uc_attribute_get_name($attribute) .'</h3>';
           foreach ($attribute->options as $option) {
@@ -593,7 +1027,7 @@ function _uc_cart_product_get_options($i
 function _uc_attribute_alter_form($product) {
   // If the product doesn't have attributes, return the form as it is.
   if (!isset($product->attributes)) {
-    $product->attributes = uc_product_get_attributes($product->nid);
+    $product->attributes = uc_attribute_load_product_attributes($product->nid);
   }
   if (!is_array($product->attributes) || empty($product->attributes)) {
     return NULL;

=== modified file 'uc_product/uc_product.module'
--- uc_product/uc_product.module	2009-06-11 12:43:49 +0000
+++ uc_product/uc_product.module	2009-06-12 10:47:22 +0000
@@ -1320,7 +1320,7 @@ function uc_catalog_buy_it_now_form($for
 function uc_catalog_buy_it_now_form_validate($form, &$form_state) {
   if (module_exists('uc_attribute')) {
     $node = node_load($form_state['values']['nid']);
-    $attributes = uc_product_get_attributes($node->nid);
+    $attributes = uc_attribute_load_product_attributes($node->nid);
     if (!empty($attributes)) {
       drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
       drupal_goto('node/'. $form_state['values']['nid']);

=== modified file 'uc_product_kit/uc_product_kit.module'
--- uc_product_kit/uc_product_kit.module	2009-05-29 14:42:03 +0000
+++ uc_product_kit/uc_product_kit.module	2009-06-12 10:47:22 +0000
@@ -762,7 +762,7 @@ function uc_product_kit_buy_it_now_form_
     $node = node_load($form_state['values']['nid']);
     if (is_array($node->products)) {
       foreach ($node->products as $nid => $product) {
-        $attributes = uc_product_get_attributes($nid);
+        $attributes = uc_attribute_load_product_attributes($nid);
         if (!empty($attributes)) {
           drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
           drupal_goto('node/'. $form_state['values']['nid']);
@@ -775,14 +775,14 @@ function uc_product_kit_buy_it_now_form_
 function uc_product_kit_buy_it_now_form_submit($form, &$form_state) {
   $node = node_load($form_state['values']['nid']);
   if (module_exists('uc_attribute')) {
-    $attributes = uc_product_get_attributes($node->nid);
+    $attributes = uc_attribute_load_product_attributes($node->nid);
     if (!empty($attributes)) {
       drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
       $form_state['redirect'] = drupal_get_path_alias('node/'. $form_state['values']['nid']);
     }
     if (is_array($node->products)) {
       foreach ($node->products as $nid => $product) {
-        $attributes = uc_product_get_attributes($nid);
+        $attributes = uc_attribute_load_product_attributes($nid);
         if (!empty($attributes)) {
           drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
           $form_state['redirect'] = drupal_get_path_alias('node/'. $form_state['values']['nid']);

