# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Classes and functions for persistence of issue tracker configuration.

This module provides functions to get, update, create, and (in some
cases) delete each type of business object.  It provides a logical
persistence layer on top of an SQL database.

Business objects are described in tracker_pb2.py and tracker_bizobj.py.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import logging

from google.appengine.api import memcache

import settings
from framework import exceptions
from framework import framework_constants
from framework import sql
from mrproto import tracker_pb2
from services import caches
from services import project_svc
from tracker import tracker_bizobj
from tracker import tracker_constants


PROJECTISSUECONFIG_TABLE_NAME = 'ProjectIssueConfig'
LABELDEF_TABLE_NAME = 'LabelDef'
FIELDDEF_TABLE_NAME = 'FieldDef'
FIELDDEF2ADMIN_TABLE_NAME = 'FieldDef2Admin'
FIELDDEF2EDITOR_TABLE_NAME = 'FieldDef2Editor'
COMPONENTDEF_TABLE_NAME = 'ComponentDef'
COMPONENT2ADMIN_TABLE_NAME = 'Component2Admin'
COMPONENT2CC_TABLE_NAME = 'Component2Cc'
COMPONENT2LABEL_TABLE_NAME = 'Component2Label'
STATUSDEF_TABLE_NAME = 'StatusDef'
APPROVALDEF2APPROVER_TABLE_NAME = 'ApprovalDef2Approver'
APPROVALDEF2SURVEY_TABLE_NAME = 'ApprovalDef2Survey'

PROJECTISSUECONFIG_COLS = [
    'project_id', 'statuses_offer_merge', 'exclusive_label_prefixes',
    'default_template_for_developers', 'default_template_for_users',
    'default_col_spec', 'default_sort_spec', 'default_x_attr',
    'default_y_attr', 'member_default_query', 'custom_issue_entry_url']
STATUSDEF_COLS = [
    'id', 'project_id', 'rank', 'status', 'means_open', 'docstring',
    'deprecated']
LABELDEF_COLS = [
    'id', 'project_id', 'rank', 'label', 'docstring', 'deprecated']
FIELDDEF_COLS = [
    'id', 'project_id', 'rank', 'field_name', 'field_type', 'applicable_type',
    'applicable_predicate', 'is_required', 'is_niche', 'is_multivalued',
    'min_value', 'max_value', 'regex', 'needs_member', 'needs_perm',
    'grants_perm', 'notify_on', 'date_action', 'docstring', 'is_deleted',
    'approval_id', 'is_phase_field', 'is_restricted_field'
]
FIELDDEF2ADMIN_COLS = ['field_id', 'admin_id']
FIELDDEF2EDITOR_COLS = ['field_id', 'editor_id']
COMPONENTDEF_COLS = ['id', 'project_id', 'path', 'docstring', 'deprecated',
                     'created', 'creator_id', 'modified', 'modifier_id']
COMPONENT2ADMIN_COLS = ['component_id', 'admin_id']
COMPONENT2CC_COLS = ['component_id', 'cc_id']
COMPONENT2LABEL_COLS = ['component_id', 'label_id']
APPROVALDEF2APPROVER_COLS = ['approval_id', 'approver_id', 'project_id']
APPROVALDEF2SURVEY_COLS = ['approval_id', 'survey', 'project_id']

NOTIFY_ON_ENUM = ['never', 'any_comment']
DATE_ACTION_ENUM = ['no_action', 'ping_owner_only', 'ping_participants']

# Some projects have tons of label rows, so we retrieve them in shards
# to avoid huge DB results or exceeding the memcache size limit.
LABEL_ROW_SHARDS = 10


class LabelRowTwoLevelCache(caches.AbstractTwoLevelCache):
  """Class to manage RAM and memcache for label rows.

  Label rows exist for every label used in a project, even those labels
  that were added to issues in an ad hoc way without being defined in the
  config ahead of time.

  The set of all labels in a project can be very large, so we shard them
  into 10 parts so that each part can be cached in memcache with < 1MB.
  """

  def __init__(self, cache_manager, config_service):
    super(LabelRowTwoLevelCache, self).__init__(
        cache_manager, 'project', 'label_rows:', None)
    self.config_service = config_service

  def _MakeCache(self, cache_manager, kind, max_size=None):
    """Make the RAM cache and registier it with the cache_manager."""
    return caches.ShardedRamCache(
      cache_manager, kind, max_size=max_size, num_shards=LABEL_ROW_SHARDS)

  def _DeserializeLabelRows(self, label_def_rows):
    """Convert DB result rows into a dict {project_id: [row, ...]}."""
    result_dict = collections.defaultdict(list)
    for label_id, project_id, rank, label, docstr, deprecated in label_def_rows:
      shard_id = label_id % LABEL_ROW_SHARDS
      result_dict[(project_id, shard_id)].append(
          (label_id, project_id, rank, label, docstr, deprecated))

    return result_dict

  def FetchItems(self, cnxn, keys):
    """On RAM and memcache miss, hit the database."""
    # Make sure that every requested project is represented in the result
    label_rows_dict = {}
    for key in keys:
      label_rows_dict.setdefault(key, [])

    for project_id, shard_id in keys:
      shard_clause = [('id %% %s = %s', [LABEL_ROW_SHARDS, shard_id])]

      label_def_rows = self.config_service.labeldef_tbl.Select(
          cnxn, cols=LABELDEF_COLS, project_id=project_id,
          where=shard_clause)
      label_rows_dict.update(self._DeserializeLabelRows(label_def_rows))

    for rows_in_shard in label_rows_dict.values():
      rows_in_shard.sort(key=lambda row: (row[2] or 0, row[3]), reverse=True)

    return label_rows_dict

  def InvalidateKeys(self, cnxn, project_ids):
    """Drop the given keys from both RAM and memcache."""
    self.cache.InvalidateKeys(cnxn, project_ids)
    memcache.delete_multi(
        [
            self._KeyToStr((project_id, shard_id))
            for project_id in project_ids
            for shard_id in range(0, LABEL_ROW_SHARDS)
        ],
        seconds=5,
        key_prefix=self.prefix,
        namespace=settings.memcache_namespace)

  def InvalidateAllKeys(self, cnxn, project_ids):
    """Drop the given keys from memcache and invalidate all keys in RAM.

    Useful for avoiding inserting many rows into the Invalidate table when
    invalidating a large group of keys all at once. Only use when necessary.
    """
    self.cache.InvalidateAll(cnxn)
    memcache.delete_multi(
        [
            self._KeyToStr((project_id, shard_id))
            for project_id in project_ids
            for shard_id in range(0, LABEL_ROW_SHARDS)
        ],
        seconds=5,
        key_prefix=self.prefix,
        namespace=settings.memcache_namespace)

  def _KeyToStr(self, key):
    """Convert our tuple IDs to strings for use as memcache keys."""
    project_id, shard_id = key
    return '%d-%d' % (project_id, shard_id)

  def _StrToKey(self, key_str):
    """Convert memcache keys back to the tuples that we use as IDs."""
    project_id_str, shard_id_str = key_str.split('-')
    return int(project_id_str), int(shard_id_str)


class StatusRowTwoLevelCache(caches.AbstractTwoLevelCache):
  """Class to manage RAM and memcache for status rows."""

  def __init__(self, cache_manager, config_service):
    super(StatusRowTwoLevelCache, self).__init__(
        cache_manager, 'project', 'status_rows:', None)
    self.config_service = config_service

  def _DeserializeStatusRows(self, def_rows):
    """Convert status definition rows into {project_id: [row, ...]}."""
    result_dict = collections.defaultdict(list)
    for (status_id, project_id, rank, status,
         means_open, docstr, deprecated) in def_rows:
      result_dict[project_id].append(
          (status_id, project_id, rank, status, means_open, docstr, deprecated))

    return result_dict

  def FetchItems(self, cnxn, keys):
    """On cache miss, get status definition rows from the DB."""
    status_def_rows = self.config_service.statusdef_tbl.Select(
        cnxn, cols=STATUSDEF_COLS, project_id=keys,
        order_by=[('rank DESC', []), ('status DESC', [])])
    status_rows_dict = self._DeserializeStatusRows(status_def_rows)

    # Make sure that every requested project is represented in the result
    for project_id in keys:
      status_rows_dict.setdefault(project_id, [])

    return status_rows_dict


class FieldRowTwoLevelCache(caches.AbstractTwoLevelCache):
  """Class to manage RAM and memcache for field rows.

  Field rows exist for every field used in a project, since they cannot be
  created through ad-hoc means.
  """

  def __init__(self, cache_manager, config_service):
    super(FieldRowTwoLevelCache, self).__init__(
        cache_manager, 'project', 'field_rows:', None)
    self.config_service = config_service

  def _DeserializeFieldRows(self, field_def_rows):
    """Convert DB result rows into a dict {project_id: [row, ...]}."""
    result_dict = collections.defaultdict(list)
    # TODO: Actually process the rest of the items.
    for (field_id, project_id, rank, field_name, _field_type, _applicable_type,
         _applicable_predicate, _is_required, _is_niche, _is_multivalued,
         _min_value, _max_value, _regex, _needs_member, _needs_perm,
         _grants_perm, _notify_on, _date_action, docstring, _is_deleted,
         _approval_id, _is_phase_field, _is_restricted_field) in field_def_rows:
      result_dict[project_id].append(
          (field_id, project_id, rank, field_name, docstring))

    return result_dict

  def FetchItems(self, cnxn, keys):
    """On RAM and memcache miss, hit the database."""
    field_def_rows = self.config_service.fielddef_tbl.Select(
        cnxn, cols=FIELDDEF_COLS, project_id=keys,
        order_by=[('rank DESC', []), ('field_name DESC', [])])
    field_rows_dict = self._DeserializeFieldRows(field_def_rows)

    # Make sure that every requested project is represented in the result
    for project_id in keys:
      field_rows_dict.setdefault(project_id, [])

    return field_rows_dict


class ConfigTwoLevelCache(caches.AbstractTwoLevelCache):
  """Class to manage RAM and memcache for IssueProjectConfig PBs."""

  def __init__(self, cache_manager, config_service):
    super(ConfigTwoLevelCache, self).__init__(
        cache_manager, 'project', 'config:', tracker_pb2.ProjectIssueConfig)
    self.config_service = config_service

  def _UnpackProjectIssueConfig(self, config_row):
    """Partially construct a config object using info from a DB row."""
    (project_id, statuses_offer_merge, exclusive_label_prefixes,
     default_template_for_developers, default_template_for_users,
     default_col_spec, default_sort_spec, default_x_attr, default_y_attr,
     member_default_query, custom_issue_entry_url) = config_row
    config = tracker_pb2.ProjectIssueConfig()
    config.project_id = project_id
    config.statuses_offer_merge.extend(statuses_offer_merge.split())
    config.exclusive_label_prefixes.extend(exclusive_label_prefixes.split())
    config.default_template_for_developers = default_template_for_developers
    config.default_template_for_users = default_template_for_users
    config.default_col_spec = default_col_spec
    config.default_sort_spec = default_sort_spec
    config.default_x_attr = default_x_attr
    config.default_y_attr = default_y_attr
    config.member_default_query = member_default_query
    if custom_issue_entry_url is not None:
      config.custom_issue_entry_url = custom_issue_entry_url

    return config

  def _UnpackFieldDef(self, fielddef_row):
    """Partially construct a FieldDef object using info from a DB row."""
    (
        field_id, project_id, _rank, field_name, field_type, applic_type,
        applic_pred, is_required, is_niche, is_multivalued, min_value,
        max_value, regex, needs_member, needs_perm, grants_perm, notify_on_str,
        date_action_str, docstring, is_deleted, approval_id, is_phase_field,
        is_restricted_field) = fielddef_row
    if notify_on_str == 'any_comment':
      notify_on = tracker_pb2.NotifyTriggers.ANY_COMMENT
    else:
      notify_on = tracker_pb2.NotifyTriggers.NEVER
    try:
      date_action = DATE_ACTION_ENUM.index(date_action_str)
    except ValueError:
      date_action = DATE_ACTION_ENUM.index('no_action')

    return tracker_bizobj.MakeFieldDef(
        field_id, project_id, field_name,
        tracker_pb2.FieldTypes(field_type.upper()), applic_type, applic_pred,
        is_required, is_niche, is_multivalued, min_value, max_value, regex,
        needs_member, needs_perm, grants_perm, notify_on, date_action,
        docstring, is_deleted, approval_id, is_phase_field, is_restricted_field)

  def _UnpackComponentDef(
      self, cd_row, component2admin_rows, component2cc_rows,
      component2label_rows):
    """Partially construct a FieldDef object using info from a DB row."""
    (component_id, project_id, path, docstring, deprecated, created,
     creator_id, modified, modifier_id) = cd_row
    cd = tracker_bizobj.MakeComponentDef(
        component_id, project_id, path, docstring, deprecated,
        [admin_id for comp_id, admin_id in component2admin_rows
         if comp_id == component_id],
        [cc_id for comp_id, cc_id in component2cc_rows
         if comp_id == component_id],
        created, creator_id,
        modified=modified, modifier_id=modifier_id,
        label_ids=[label_id for comp_id, label_id in component2label_rows
                   if comp_id == component_id])

    return cd

  def _DeserializeIssueConfigs(
      self, config_rows, statusdef_rows, labeldef_rows, fielddef_rows,
      fielddef2admin_rows, fielddef2editor_rows, componentdef_rows,
      component2admin_rows, component2cc_rows, component2label_rows,
      approvaldef2approver_rows, approvaldef2survey_rows):
    """Convert the given row tuples into a dict of ProjectIssueConfig PBs."""
    result_dict = {}
    fielddef_dict = {}
    approvaldef_dict = {}

    for config_row in config_rows:
      config = self._UnpackProjectIssueConfig(config_row)
      result_dict[config.project_id] = config

    for statusdef_row in statusdef_rows:
      (_, project_id, _rank, status,
       means_open, docstring, deprecated) = statusdef_row
      if project_id in result_dict:
        wks = tracker_pb2.StatusDef(
            status=status, means_open=bool(means_open),
            status_docstring=docstring or '', deprecated=bool(deprecated))
        result_dict[project_id].well_known_statuses.append(wks)

    for labeldef_row in labeldef_rows:
      _, project_id, _rank, label, docstring, deprecated = labeldef_row
      if project_id in result_dict:
        wkl = tracker_pb2.LabelDef(
            label=label, label_docstring=docstring or '',
            deprecated=bool(deprecated))
        result_dict[project_id].well_known_labels.append(wkl)

    for approver_row in approvaldef2approver_rows:
      approval_id, approver_id, project_id = approver_row
      if project_id in result_dict:
        approval_def = approvaldef_dict.get(approval_id)
        if approval_def is None:
          approval_def = tracker_pb2.ApprovalDef(
              approval_id=approval_id)
          result_dict[project_id].approval_defs.append(approval_def)
          approvaldef_dict[approval_id] = approval_def
        approval_def.approver_ids.append(approver_id)

    for survey_row in approvaldef2survey_rows:
      approval_id, survey, project_id = survey_row
      if project_id in result_dict:
        approval_def = approvaldef_dict.get(approval_id)
        if approval_def is None:
          approval_def = tracker_pb2.ApprovalDef(
              approval_id=approval_id)
          result_dict[project_id].approval_defs.append(approval_def)
          approvaldef_dict[approval_id] = approval_def
        approval_def.survey = survey

    for fd_row in fielddef_rows:
      fd = self._UnpackFieldDef(fd_row)
      result_dict[fd.project_id].field_defs.append(fd)
      fielddef_dict[fd.field_id] = fd

    for fd2admin_row in fielddef2admin_rows:
      field_id, admin_id = fd2admin_row
      fd = fielddef_dict.get(field_id)
      if fd:
        fd.admin_ids.append(admin_id)

    for fd2editor_row in fielddef2editor_rows:
      field_id, editor_id = fd2editor_row
      fd = fielddef_dict.get(field_id)
      if fd:
        fd.editor_ids.append(editor_id)

    for cd_row in componentdef_rows:
      cd = self._UnpackComponentDef(
          cd_row, component2admin_rows, component2cc_rows, component2label_rows)
      result_dict[cd.project_id].component_defs.append(cd)

    return result_dict

  def _FetchConfigs(self, cnxn, project_ids):
    """On RAM and memcache miss, hit the database."""
    config_rows = self.config_service.projectissueconfig_tbl.Select(
        cnxn, cols=PROJECTISSUECONFIG_COLS, project_id=project_ids)
    statusdef_rows = self.config_service.statusdef_tbl.Select(
        cnxn, cols=STATUSDEF_COLS, project_id=project_ids,
        where=[('rank IS NOT NULL', [])], order_by=[('rank', [])])

    labeldef_rows = self.config_service.labeldef_tbl.Select(
        cnxn, cols=LABELDEF_COLS, project_id=project_ids,
        where=[('rank IS NOT NULL', [])], order_by=[('rank', [])])

    approver_rows = self.config_service.approvaldef2approver_tbl.Select(
        cnxn, cols=APPROVALDEF2APPROVER_COLS, project_id=project_ids)
    survey_rows = self.config_service.approvaldef2survey_tbl.Select(
        cnxn, cols=APPROVALDEF2SURVEY_COLS, project_id=project_ids)

    # TODO(jrobbins): For now, sort by field name, but someday allow admins
    # to adjust the rank to group and order field definitions logically.
    fielddef_rows = self.config_service.fielddef_tbl.Select(
        cnxn, cols=FIELDDEF_COLS, project_id=project_ids,
        order_by=[('field_name', [])])
    field_ids = [row[0] for row in fielddef_rows]
    fielddef2admin_rows = []
    fielddef2editor_rows = []
    if field_ids:
      fielddef2admin_rows = self.config_service.fielddef2admin_tbl.Select(
          cnxn, cols=FIELDDEF2ADMIN_COLS, field_id=field_ids)
      fielddef2editor_rows = self.config_service.fielddef2editor_tbl.Select(
          cnxn, cols=FIELDDEF2EDITOR_COLS, field_id=field_ids)

    componentdef_rows = self.config_service.componentdef_tbl.Select(
        cnxn, cols=COMPONENTDEF_COLS, project_id=project_ids,
        is_deleted=False, order_by=[('path', [])])
    component_ids = [cd_row[0] for cd_row in componentdef_rows]
    component2admin_rows = []
    component2cc_rows = []
    component2label_rows = []
    if component_ids:
      component2admin_rows = self.config_service.component2admin_tbl.Select(
          cnxn, cols=COMPONENT2ADMIN_COLS, component_id=component_ids)
      component2cc_rows = self.config_service.component2cc_tbl.Select(
          cnxn, cols=COMPONENT2CC_COLS, component_id=component_ids)
      component2label_rows = self.config_service.component2label_tbl.Select(
          cnxn, cols=COMPONENT2LABEL_COLS, component_id=component_ids)

    retrieved_dict = self._DeserializeIssueConfigs(
        config_rows, statusdef_rows, labeldef_rows, fielddef_rows,
        fielddef2admin_rows, fielddef2editor_rows, componentdef_rows,
        component2admin_rows, component2cc_rows, component2label_rows,
        approver_rows, survey_rows)
    return retrieved_dict

  def FetchItems(self, cnxn, keys):
    """On RAM and memcache miss, hit the database."""
    retrieved_dict = self._FetchConfigs(cnxn, keys)

    # Any projects which don't have stored configs should use a default
    # config instead.
    for project_id in keys:
      if project_id not in retrieved_dict:
        config = tracker_bizobj.MakeDefaultProjectIssueConfig(project_id)
        retrieved_dict[project_id] = config

    return retrieved_dict


class ConfigService(object):
  """The persistence layer for Monorail's issue tracker configuration data."""

  def __init__(self, cache_manager):
    """Initialize this object so that it is ready to use.

    Args:
      cache_manager: manages local caches with distributed invalidation.
    """
    self.projectissueconfig_tbl = sql.SQLTableManager(
        PROJECTISSUECONFIG_TABLE_NAME)
    self.statusdef_tbl = sql.SQLTableManager(STATUSDEF_TABLE_NAME)
    self.labeldef_tbl = sql.SQLTableManager(LABELDEF_TABLE_NAME)
    self.fielddef_tbl = sql.SQLTableManager(FIELDDEF_TABLE_NAME)
    self.fielddef2admin_tbl = sql.SQLTableManager(FIELDDEF2ADMIN_TABLE_NAME)
    self.fielddef2editor_tbl = sql.SQLTableManager(FIELDDEF2EDITOR_TABLE_NAME)
    self.componentdef_tbl = sql.SQLTableManager(COMPONENTDEF_TABLE_NAME)
    self.component2admin_tbl = sql.SQLTableManager(COMPONENT2ADMIN_TABLE_NAME)
    self.component2cc_tbl = sql.SQLTableManager(COMPONENT2CC_TABLE_NAME)
    self.component2label_tbl = sql.SQLTableManager(COMPONENT2LABEL_TABLE_NAME)
    self.approvaldef2approver_tbl = sql.SQLTableManager(
        APPROVALDEF2APPROVER_TABLE_NAME)
    self.approvaldef2survey_tbl = sql.SQLTableManager(
        APPROVALDEF2SURVEY_TABLE_NAME)

    self.config_2lc = ConfigTwoLevelCache(cache_manager, self)
    self.label_row_2lc = LabelRowTwoLevelCache(cache_manager, self)
    self.label_cache = caches.RamCache(cache_manager, 'project')
    self.status_row_2lc = StatusRowTwoLevelCache(cache_manager, self)
    self.status_cache = caches.RamCache(cache_manager, 'project')
    self.field_row_2lc = FieldRowTwoLevelCache(cache_manager, self)
    self.field_cache = caches.RamCache(cache_manager, 'project')

  ### Label lookups

  def GetLabelDefRows(self, cnxn, project_id, use_cache=True):
    """Get SQL result rows for all labels used in the specified project."""
    result = []
    for shard_id in range(0, LABEL_ROW_SHARDS):
      key = (project_id, shard_id)
      pids_to_label_rows_shard, _misses = self.label_row_2lc.GetAll(
        cnxn, [key], use_cache=use_cache)
      result.extend(pids_to_label_rows_shard[key])
    # Sort in python to reduce DB load and integrate results from shards.
    # row[2] is rank, row[3] is label name.
    result.sort(key=lambda row: (row[2] or 0, row[3]), reverse=True)
    return result

  def GetLabelDefRowsAnyProject(self, cnxn, where=None):
    """Get all LabelDef rows for the whole site. Used in whole-site search."""
    # TODO(jrobbins): maybe add caching for these too.
    label_def_rows = self.labeldef_tbl.Select(
        cnxn, cols=LABELDEF_COLS, where=where,
        order_by=[('rank DESC', []), ('label DESC', [])])
    return label_def_rows

  def _DeserializeLabels(self, def_rows):
    """Convert label defs into bi-directional mappings of names and IDs."""
    label_id_to_name = {
        label_id: label for
        label_id, _pid, _rank, label, _doc, _deprecated
        in def_rows}
    label_name_to_id = {
        label.lower(): label_id
        for label_id, label in label_id_to_name.items()}

    return label_id_to_name, label_name_to_id

  def _EnsureLabelCacheEntry(self, cnxn, project_id, use_cache=True):
    """Make sure that self.label_cache has an entry for project_id."""
    if not use_cache or not self.label_cache.HasItem(project_id):
      def_rows = self.GetLabelDefRows(cnxn, project_id, use_cache=use_cache)
      self.label_cache.CacheItem(project_id, self._DeserializeLabels(def_rows))

  def LookupLabel(self, cnxn, project_id, label_id):
    """Lookup a label string given the label_id.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the label is defined or used.
      label_id: int label ID.

    Returns:
      Label name string for the given label_id, or None.
    """
    self._EnsureLabelCacheEntry(cnxn, project_id)
    label_id_to_name, _label_name_to_id = self.label_cache.GetItem(
        project_id)
    if label_id in label_id_to_name:
      return label_id_to_name[label_id]

    logging.info('Label %r not found. Getting fresh from DB.', label_id)
    self._EnsureLabelCacheEntry(cnxn, project_id, use_cache=False)
    label_id_to_name, _label_name_to_id = self.label_cache.GetItem(
        project_id)
    return label_id_to_name.get(label_id)

  def LookupLabelID(
      self, cnxn, project_id, label, autocreate=True, case_sensitive=False):
    """Look up a label ID, optionally interning it.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the statuses are defined.
      label: label string.
      autocreate: if not already in the DB, store it and generate a new ID.
      case_sensitive: if label lookup is case sensivite

    Returns:
      The label ID for the given label string.
    """
    self._EnsureLabelCacheEntry(cnxn, project_id)
    _label_id_to_name, label_name_to_id = self.label_cache.GetItem(
        project_id)

    label_lower = label.lower() if not case_sensitive else label
    if label_lower in label_name_to_id:
      return label_name_to_id[label_lower]

    if not case_sensitive:
      where = [('LOWER(label) = %s', [label_lower])]
    else:
      where = [('label = %s', [label])]

    # Double check that the label does not already exist in the DB.
    rows = self.labeldef_tbl.Select(
        cnxn, cols=['id'], project_id=project_id, where=where, limit=1)
    logging.info('Double checking for %r gave %r', label, rows)
    if rows:
      self.label_row_2lc.cache.LocalInvalidate(project_id)
      self.label_cache.LocalInvalidate(project_id)
      return rows[0][0]

    if autocreate:
      logging.info('No label %r is known in project %d, so intern it.',
                   label, project_id)
      label_id = self.labeldef_tbl.InsertRow(
          cnxn, project_id=project_id, label=label)
      self.label_row_2lc.InvalidateKeys(cnxn, [project_id])
      self.label_cache.Invalidate(cnxn, project_id)
      return label_id

    return None  # It was not found and we don't want to create it.

  def LookupLabelIDs(self, cnxn, project_id, labels, autocreate=False):
    """Look up several label IDs.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the statuses are defined.
      labels: list of label strings.
      autocreate: if not already in the DB, store it and generate a new ID.

    Returns:
      Returns a list of int label IDs for the given label strings.
    """
    result = []
    for lab in labels:
      label_id = self.LookupLabelID(
          cnxn, project_id, lab, autocreate=autocreate)
      if label_id is not None:
        result.append(label_id)

    return result

  def LookupIDsOfLabelsMatching(self, cnxn, project_id, regex):
    """Look up the IDs of all labels in a project that match the regex.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the statuses are defined.
      regex: regular expression object to match against the label strings.

    Returns:
      List of label IDs for labels that match the regex.
    """
    self._EnsureLabelCacheEntry(cnxn, project_id)
    label_id_to_name, _label_name_to_id = self.label_cache.GetItem(
        project_id)
    result = [label_id for label_id, label in label_id_to_name.items()
              if regex.match(label)]

    return result

  def LookupLabelIDsAnyProject(self, cnxn, label):
    """Return the IDs of labels with the given name in any project.

    Args:
      cnxn: connection to SQL database.
      label: string label to look up.  Case sensitive.

    Returns:
      A list of int label IDs of all labels matching the given string.
    """
    # TODO(jrobbins): maybe add caching for these too.
    label_id_rows = self.labeldef_tbl.Select(
        cnxn, cols=['id'], label=label)
    label_ids = [row[0] for row in label_id_rows]
    return label_ids

  def LookupIDsOfLabelsMatchingAnyProject(self, cnxn, regex):
    """Return the IDs of matching labels in any project."""
    label_rows = self.labeldef_tbl.Select(
        cnxn, cols=['id', 'label'])
    matching_ids = [
        label_id for label_id, label in label_rows if regex.match(label)]
    return matching_ids

  ### Status lookups

  def GetStatusDefRows(self, cnxn, project_id):
    """Return a list of status definition rows for the specified project."""
    pids_to_status_rows, misses = self.status_row_2lc.GetAll(
        cnxn, [project_id])
    assert not misses
    return pids_to_status_rows[project_id]

  def GetStatusDefRowsAnyProject(self, cnxn):
    """Return all status definition rows on the whole site."""
    # TODO(jrobbins): maybe add caching for these too.
    status_def_rows = self.statusdef_tbl.Select(
        cnxn, cols=STATUSDEF_COLS,
        order_by=[('rank DESC', []), ('status DESC', [])])
    return status_def_rows

  def _DeserializeStatuses(self, def_rows):
    """Convert status defs into bi-directional mappings of names and IDs."""
    status_id_to_name = {
        status_id: status
        for (status_id, _pid, _rank, status, _means_open,
             _doc, _deprecated) in def_rows}
    status_name_to_id = {
        status.lower(): status_id
        for status_id, status in status_id_to_name.items()}
    closed_status_ids = [
        status_id
        for (status_id, _pid, _rank, _status, means_open,
             _doc, _deprecated) in def_rows
        if means_open == 0]  # Only 0 means closed. NULL/None means open.

    return status_id_to_name, status_name_to_id, closed_status_ids

  def _EnsureStatusCacheEntry(self, cnxn, project_id):
    """Make sure that self.status_cache has an entry for project_id."""
    if not self.status_cache.HasItem(project_id):
      def_rows = self.GetStatusDefRows(cnxn, project_id)
      self.status_cache.CacheItem(
          project_id, self._DeserializeStatuses(def_rows))

  def LookupStatus(self, cnxn, project_id, status_id):
    """Look up a status string for the given status ID.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the statuses are defined.
      status_id: int ID of the status value.

    Returns:
      A status string, or None.
    """
    if status_id == 0:
      return ''

    self._EnsureStatusCacheEntry(cnxn, project_id)
    (status_id_to_name, _status_name_to_id,
     _closed_status_ids) = self.status_cache.GetItem(project_id)

    return status_id_to_name.get(status_id)

  def LookupStatusID(self, cnxn, project_id, status, autocreate=True):
    """Look up a status ID for the given status string.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the statuses are defined.
      status: status string.
      autocreate: if not already in the DB, store it and generate a new ID.

    Returns:
      The status ID for the given status string, or None.
    """
    if not status:
      return None

    self._EnsureStatusCacheEntry(cnxn, project_id)
    (_status_id_to_name, status_name_to_id,
     _closed_status_ids) = self.status_cache.GetItem(project_id)
    if status.lower() in status_name_to_id:
      return status_name_to_id[status.lower()]

    if autocreate:
      logging.info('No status %r is known in project %d, so intern it.',
                   status, project_id)
      status_id = self.statusdef_tbl.InsertRow(
          cnxn, project_id=project_id, status=status)
      self.status_row_2lc.InvalidateKeys(cnxn, [project_id])
      self.status_cache.Invalidate(cnxn, project_id)
      return status_id

    return None  # It was not found and we don't want to create it.

  def LookupStatusIDs(self, cnxn, project_id, statuses):
    """Look up several status IDs for the given status strings.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the statuses are defined.
      statuses: list of status strings.

    Returns:
      A list of int status IDs.
    """
    result = []
    for stat in statuses:
      status_id = self.LookupStatusID(cnxn, project_id, stat, autocreate=False)
      if status_id:
        result.append(status_id)

    return result

  def LookupClosedStatusIDs(self, cnxn, project_id):
    """Return the IDs of closed statuses defined in the given project."""
    self._EnsureStatusCacheEntry(cnxn, project_id)
    (_status_id_to_name, _status_name_to_id,
     closed_status_ids) = self.status_cache.GetItem(project_id)

    return closed_status_ids

  def LookupClosedStatusIDsAnyProject(self, cnxn):
    """Return the IDs of closed statuses defined in any project."""
    status_id_rows = self.statusdef_tbl.Select(
        cnxn, cols=['id'], means_open=False)
    status_ids = [row[0] for row in status_id_rows]
    return status_ids

  def LookupStatusIDsAnyProject(self, cnxn, status):
    """Return the IDs of statues with the given name in any project."""
    status_id_rows = self.statusdef_tbl.Select(
        cnxn, cols=['id'], status=status)
    status_ids = [row[0] for row in status_id_rows]
    return status_ids

  # TODO(jrobbins): regex matching for status values.

  ### Issue tracker configuration objects

  def GetProjectConfigs(self, cnxn, project_ids, use_cache=True):
    # type: (MonorailConnection, Collection[int], Optional[bool])
    #     -> Mapping[int, ProjectConfig]
    """Get several project issue config objects."""
    config_dict, missed_ids = self.config_2lc.GetAll(
        cnxn, project_ids, use_cache=use_cache)
    if missed_ids:
      raise exceptions.NoSuchProjectException()
    return config_dict

  def GetProjectConfig(self, cnxn, project_id, use_cache=True):
    """Load a ProjectIssueConfig for the specified project from the database.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the current project.
      use_cache: if False, always hit the database.

    Returns:
      A ProjectIssueConfig describing how the issue tracker in the specified
      project is configured.  Projects only have a stored ProjectIssueConfig if
      a project owner has edited the configuration.  Other projects use a
      default configuration.
    """
    config_dict = self.GetProjectConfigs(
        cnxn, [project_id], use_cache=use_cache)
    return config_dict[project_id]

  def StoreConfig(self, cnxn, config):
    """Update an issue config in the database.

    Args:
      cnxn: connection to SQL database.
      config: ProjectIssueConfig PB to update.
    """
    # TODO(jrobbins): Convert default template index values into foreign
    # key references.  Updating an entire config might require (1) adding
    # new templates, (2) updating the config with new foreign key values,
    # and finally (3) deleting only the specific templates that should be
    # deleted.
    self.projectissueconfig_tbl.InsertRow(
        cnxn, replace=True,
        project_id=config.project_id,
        statuses_offer_merge=' '.join(config.statuses_offer_merge),
        exclusive_label_prefixes=' '.join(config.exclusive_label_prefixes),
        default_template_for_developers=config.default_template_for_developers,
        default_template_for_users=config.default_template_for_users,
        default_col_spec=config.default_col_spec,
        default_sort_spec=config.default_sort_spec,
        default_x_attr=config.default_x_attr,
        default_y_attr=config.default_y_attr,
        member_default_query=config.member_default_query,
        custom_issue_entry_url=config.custom_issue_entry_url,
        commit=False)

    self._UpdateWellKnownLabels(cnxn, config)
    self._UpdateWellKnownStatuses(cnxn, config)
    self._UpdateApprovals(cnxn, config)
    cnxn.Commit()

  def _UpdateWellKnownLabels(self, cnxn, config):
    """Update the labels part of a project's issue configuration.

    Args:
      cnxn: connection to SQL database.
      config: ProjectIssueConfig PB to update in the DB.
    """
    update_labeldef_rows = []
    new_labeldef_rows = []
    labels_seen = set()
    for rank, wkl in enumerate(config.well_known_labels):
      # Prevent duplicate key errors
      if wkl.label in labels_seen:
        raise exceptions.InputException('Defined label "%s" twice' % wkl.label)
      labels_seen.add(wkl.label)
      # We must specify label ID when replacing, otherwise a new ID is made.
      label_id = self.LookupLabelID(
          cnxn, config.project_id, wkl.label, autocreate=False)
      if label_id:
        row = (label_id, config.project_id, rank, wkl.label,
               wkl.label_docstring, wkl.deprecated)
        update_labeldef_rows.append(row)
      else:
        row = (
            config.project_id, rank, wkl.label, wkl.label_docstring,
            wkl.deprecated)
        new_labeldef_rows.append(row)

    self.labeldef_tbl.Update(
        cnxn, {'rank': None}, project_id=config.project_id, commit=False)
    self.labeldef_tbl.InsertRows(
        cnxn, LABELDEF_COLS, update_labeldef_rows, replace=True, commit=False)
    self.labeldef_tbl.InsertRows(
        cnxn, LABELDEF_COLS[1:], new_labeldef_rows, commit=False)
    self.label_row_2lc.InvalidateKeys(cnxn, [config.project_id])
    self.label_cache.Invalidate(cnxn, config.project_id)

  def _UpdateWellKnownStatuses(self, cnxn, config):
    """Update the status part of a project's issue configuration.

    Args:
      cnxn: connection to SQL database.
      config: ProjectIssueConfig PB to update in the DB.
    """
    update_statusdef_rows = []
    new_statusdef_rows = []
    for rank, wks in enumerate(config.well_known_statuses):
      # We must specify label ID when replacing, otherwise a new ID is made.
      status_id = self.LookupStatusID(cnxn, config.project_id, wks.status,
                                      autocreate=False)
      if status_id is not None:
        row = (status_id, config.project_id, rank, wks.status,
               bool(wks.means_open), wks.status_docstring, wks.deprecated)
        update_statusdef_rows.append(row)
      else:
        row = (config.project_id, rank, wks.status,
               bool(wks.means_open), wks.status_docstring, wks.deprecated)
        new_statusdef_rows.append(row)

    self.statusdef_tbl.Update(
        cnxn, {'rank': None}, project_id=config.project_id, commit=False)
    self.statusdef_tbl.InsertRows(
        cnxn, STATUSDEF_COLS, update_statusdef_rows, replace=True,
        commit=False)
    self.statusdef_tbl.InsertRows(
        cnxn, STATUSDEF_COLS[1:], new_statusdef_rows, commit=False)
    self.status_row_2lc.InvalidateKeys(cnxn, [config.project_id])
    self.status_cache.Invalidate(cnxn, config.project_id)

  def _UpdateApprovals(self, cnxn, config):
    """Update the approvals part of a project's issue configuration.

    Args:
      cnxn: connection to SQL database.
      config: ProjectIssueConfig PB to update in the DB.
    """
    ids_to_field_def = {fd.field_id: fd for fd in config.field_defs}
    for approval_def in config.approval_defs:
      try:
        approval_fd = ids_to_field_def[approval_def.approval_id]
        if approval_fd.field_type != tracker_pb2.FieldTypes.APPROVAL_TYPE:
          raise exceptions.InvalidFieldTypeException()
      except KeyError:
        raise exceptions.NoSuchFieldDefException()

      self.approvaldef2approver_tbl.Delete(
          cnxn, approval_id=approval_def.approval_id, commit=False)

      self.approvaldef2approver_tbl.InsertRows(
          cnxn, APPROVALDEF2APPROVER_COLS,
          [(approval_def.approval_id, approver_id, config.project_id) for
           approver_id in approval_def.approver_ids],
          commit=False)

      self.approvaldef2survey_tbl.Delete(
          cnxn, approval_id=approval_def.approval_id, commit=False)
      self.approvaldef2survey_tbl.InsertRow(
          cnxn, approval_id=approval_def.approval_id,
          survey=approval_def.survey, project_id=config.project_id,
          commit=False)

  def UpdateConfig(
      self, cnxn, project, well_known_statuses=None,
      statuses_offer_merge=None, well_known_labels=None,
      excl_label_prefixes=None, default_template_for_developers=None,
      default_template_for_users=None, list_prefs=None, restrict_to_known=None,
      approval_defs=None):
    """Update project's issue tracker configuration with the given info.

    Args:
      cnxn: connection to SQL database.
      project: the project in which to update the issue tracker config.
      well_known_statuses: [(status_name, docstring, means_open, deprecated),..]
      statuses_offer_merge: list of status values that trigger UI to merge.
      well_known_labels: [(label_name, docstring, deprecated),...]
      excl_label_prefixes: list of prefix strings.  Each issue should
          have only one label with each of these prefixed.
      default_template_for_developers: int ID of template to use for devs.
      default_template_for_users: int ID of template to use for non-members.
      list_prefs: defaults for columns and sorting.
      restrict_to_known: optional bool to allow project owners
          to limit issue status and label values to only the well-known ones.
      approval_defs: [(approval_id, approver_ids, survey), ..]

    Returns:
      The updated ProjectIssueConfig PB.
    """
    project_id = project.project_id
    project_config = self.GetProjectConfig(cnxn, project_id, use_cache=False)

    if well_known_statuses is not None:
      tracker_bizobj.SetConfigStatuses(project_config, well_known_statuses)

    if statuses_offer_merge is not None:
      project_config.statuses_offer_merge = statuses_offer_merge

    if well_known_labels is not None:
      tracker_bizobj.SetConfigLabels(project_config, well_known_labels)

    if excl_label_prefixes is not None:
      project_config.exclusive_label_prefixes = excl_label_prefixes

    if approval_defs is not None:
      tracker_bizobj.SetConfigApprovals(project_config, approval_defs)

    if default_template_for_developers is not None:
      project_config.default_template_for_developers = (
          default_template_for_developers)
    if default_template_for_users is not None:
      project_config.default_template_for_users = default_template_for_users

    if list_prefs:
      (default_col_spec, default_sort_spec, default_x_attr, default_y_attr,
       member_default_query) = list_prefs
      project_config.default_col_spec = default_col_spec
      project_config.default_col_spec = default_col_spec
      project_config.default_sort_spec = default_sort_spec
      project_config.default_x_attr = default_x_attr
      project_config.default_y_attr = default_y_attr
      project_config.member_default_query = member_default_query

    if restrict_to_known is not None:
      project_config.restrict_to_known = restrict_to_known

    self.StoreConfig(cnxn, project_config)
    self.config_2lc.InvalidateKeys(cnxn, [project_id])
    self.InvalidateMemcacheForEntireProject(project_id)
    # Invalidate all issue caches in all frontends to clear out
    # sorting.art_values_cache which now has wrong sort orders.
    cache_manager = self.config_2lc.cache.cache_manager
    cache_manager.StoreInvalidateAll(cnxn, 'issue')

    return project_config

  def ExpungeConfig(self, cnxn, project_id):
    """Completely delete the specified project config from the database."""
    logging.info('expunging the config for %r', project_id)
    self.statusdef_tbl.Delete(cnxn, project_id=project_id)
    self.labeldef_tbl.Delete(cnxn, project_id=project_id)
    self.projectissueconfig_tbl.Delete(cnxn, project_id=project_id)

    self.config_2lc.InvalidateKeys(cnxn, [project_id])

  def ExpungeUsersInConfigs(self, cnxn, user_ids, limit=None):
    """Wipes specified users from the configs system.

      This method will not commit the operation. This method will
      not make changes to in-memory data.
    """
    self.component2admin_tbl.Delete(
        cnxn, admin_id=user_ids, commit=False, limit=limit)
    self.component2cc_tbl.Delete(
        cnxn, cc_id=user_ids, commit=False, limit=limit)
    self.componentdef_tbl.Update(
        cnxn, {'creator_id': framework_constants.DELETED_USER_ID},
        creator_id=user_ids, commit=False, limit=limit)
    self.componentdef_tbl.Update(
        cnxn, {'modifier_id': framework_constants.DELETED_USER_ID},
        modifier_id=user_ids, commit=False, limit=limit)
    self.fielddef2admin_tbl.Delete(
        cnxn, admin_id=user_ids, commit=False, limit=limit)
    self.fielddef2editor_tbl.Delete(
        cnxn, editor_id=user_ids, commit=False, limit=limit)
    self.approvaldef2approver_tbl.Delete(
        cnxn, approver_id=user_ids, commit=False, limit=limit)

  ### Custom field definitions

  def CreateFieldDef(
      self,
      cnxn,
      project_id,
      field_name,
      field_type_str,
      applic_type,
      applic_pred,
      is_required,
      is_niche,
      is_multivalued,
      min_value,
      max_value,
      regex,
      needs_member,
      needs_perm,
      grants_perm,
      notify_on,
      date_action_str,
      docstring,
      admin_ids,
      editor_ids,
      approval_id=None,
      is_phase_field=False,
      is_restricted_field=False):
    """Create a new field definition with the given info.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the current project.
      field_name: name of the new custom field.
      field_type_str: string identifying the type of the custom field.
      applic_type: string specifying issue type the field is applicable to.
      applic_pred: string condition to test if the field is applicable.
      is_required: True if the field should be required on issues.
      is_niche: True if the field is not initially offered for editing, so users
          must click to reveal such special-purpose or experimental fields.
      is_multivalued: True if the field can occur multiple times on one issue.
      min_value: optional validation for int_type fields.
      max_value: optional validation for int_type fields.
      regex: optional validation for str_type fields.
      needs_member: optional validation for user_type fields.
      needs_perm: optional validation for user_type fields.
      grants_perm: optional string for perm to grant any user named in field.
      notify_on: int enum of when to notify users named in field.
      date_action_str: string saying who to notify when a date arrives.
      docstring: string describing this field.
      admin_ids: list of additional user IDs who can edit this field def.
      editor_ids: list of additional user IDs
          who can edit a restricted field value.
      approval_id: field_id of approval field this field belongs to.
      is_phase_field: True if field should only be associated with issue phases.
      is_restricted_field: True if field has its edition restricted.

    Returns:
      Integer field_id of the new field definition.
    """
    field_id = self.fielddef_tbl.InsertRow(
        cnxn,
        project_id=project_id,
        field_name=field_name,
        field_type=field_type_str,
        applicable_type=applic_type,
        applicable_predicate=applic_pred,
        is_required=is_required,
        is_niche=is_niche,
        is_multivalued=is_multivalued,
        min_value=min_value,
        max_value=max_value,
        regex=regex,
        needs_member=needs_member,
        needs_perm=needs_perm,
        grants_perm=grants_perm,
        notify_on=NOTIFY_ON_ENUM[notify_on],
        date_action=date_action_str,
        docstring=docstring,
        approval_id=approval_id,
        is_phase_field=is_phase_field,
        is_restricted_field=is_restricted_field,
        commit=False)
    self.fielddef2admin_tbl.InsertRows(
        cnxn, FIELDDEF2ADMIN_COLS,
        [(field_id, admin_id) for admin_id in admin_ids],
        commit=False)
    self.fielddef2editor_tbl.InsertRows(
        cnxn,
        FIELDDEF2EDITOR_COLS,
        [(field_id, editor_id) for editor_id in editor_ids],
        commit=False)
    cnxn.Commit()
    self.config_2lc.InvalidateKeys(cnxn, [project_id])
    self.field_row_2lc.InvalidateKeys(cnxn, [project_id])
    self.InvalidateMemcacheForEntireProject(project_id)
    return field_id

  def _DeserializeFields(self, def_rows):
    """Convert field defs into bi-directional mappings of names and IDs."""
    field_id_to_name = {
        field_id: field
        for field_id, _pid, _rank, field, _doc in def_rows}
    field_name_to_id = {
        field.lower(): field_id
        for field_id, field in field_id_to_name.items()}

    return field_id_to_name, field_name_to_id

  def GetFieldDefRows(self, cnxn, project_id):
    """Get SQL result rows for all fields used in the specified project."""
    pids_to_field_rows, misses = self.field_row_2lc.GetAll(cnxn, [project_id])
    assert not misses
    return pids_to_field_rows[project_id]

  def _EnsureFieldCacheEntry(self, cnxn, project_id):
    """Make sure that self.field_cache has an entry for project_id."""
    if not self.field_cache.HasItem(project_id):
      def_rows = self.GetFieldDefRows(cnxn, project_id)
      self.field_cache.CacheItem(
          project_id, self._DeserializeFields(def_rows))

  def LookupField(self, cnxn, project_id, field_id):
    """Lookup a field string given the field_id.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the label is defined or used.
      field_id: int field ID.

    Returns:
      Field name string for the given field_id, or None.
    """
    self._EnsureFieldCacheEntry(cnxn, project_id)
    field_id_to_name, _field_name_to_id = self.field_cache.GetItem(
        project_id)
    return field_id_to_name.get(field_id)

  def LookupFieldID(self, cnxn, project_id, field):
    """Look up a field ID.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the project where the fields are defined.
      field: field string.

    Returns:
      The field ID for the given field string.
    """
    self._EnsureFieldCacheEntry(cnxn, project_id)
    _field_id_to_name, field_name_to_id = self.field_cache.GetItem(
        project_id)
    return field_name_to_id.get(field.lower())

  def SoftDeleteFieldDefs(self, cnxn, project_id, field_ids):
    """Mark the specified field as deleted, it will be reaped later."""
    self.fielddef_tbl.Update(cnxn, {'is_deleted': True}, id=field_ids)
    self.config_2lc.InvalidateKeys(cnxn, [project_id])
    self.InvalidateMemcacheForEntireProject(project_id)

  # TODO(jrobbins): GC deleted field defs after field values are gone.

  def UpdateFieldDef(
      self,
      cnxn,
      project_id,
      field_id,
      field_name=None,
      applicable_type=None,
      applicable_predicate=None,
      is_required=None,
      is_niche=None,
      is_multivalued=None,
      min_value=None,
      max_value=None,
      regex=None,
      needs_member=None,
      needs_perm=None,
      grants_perm=None,
      notify_on=None,
      date_action=None,
      docstring=None,
      admin_ids=None,
      editor_ids=None,
      is_restricted_field=None):
    """Update the specified field definition."""
    new_values = {}
    if field_name is not None:
      new_values['field_name'] = field_name
    if applicable_type is not None:
      new_values['applicable_type'] = applicable_type
    if applicable_predicate is not None:
      new_values['applicable_predicate'] = applicable_predicate
    if is_required is not None:
      new_values['is_required'] = bool(is_required)
    if is_niche is not None:
      new_values['is_niche'] = bool(is_niche)
    if is_multivalued is not None:
      new_values['is_multivalued'] = bool(is_multivalued)
    if min_value is not None:
      new_values['min_value'] = min_value
    if max_value is not None:
      new_values['max_value'] = max_value
    if regex is not None:
      new_values['regex'] = regex
    if needs_member is not None:
      new_values['needs_member'] = needs_member
    if needs_perm is not None:
      new_values['needs_perm'] = needs_perm
    if grants_perm is not None:
      new_values['grants_perm'] = grants_perm
    if notify_on is not None:
      new_values['notify_on'] = NOTIFY_ON_ENUM[notify_on]
    if date_action is not None:
      new_values['date_action'] = date_action
    if docstring is not None:
      new_values['docstring'] = docstring
    if is_restricted_field is not None:
      new_values['is_restricted_field'] = is_restricted_field

    self.fielddef_tbl.Update(cnxn, new_values, id=field_id, commit=False)
    if admin_ids is not None:
      self.fielddef2admin_tbl.Delete(cnxn, field_id=field_id, commit=False)
      self.fielddef2admin_tbl.InsertRows(
          cnxn,
          FIELDDEF2ADMIN_COLS, [(field_id, admin_id) for admin_id in admin_ids],
          commit=False)
    if editor_ids is not None:
      self.fielddef2editor_tbl.Delete(cnxn, field_id=field_id, commit=False)
      self.fielddef2editor_tbl.InsertRows(
          cnxn,
          FIELDDEF2EDITOR_COLS,
          [(field_id, editor_id) for editor_id in editor_ids],
          commit=False)
    cnxn.Commit()
    self.config_2lc.InvalidateKeys(cnxn, [project_id])
    self.InvalidateMemcacheForEntireProject(project_id)

  ### Component definitions

  def FindMatchingComponentIDsAnyProject(self, cnxn, path_list, exact=True):
    """Look up component IDs across projects.

    Args:
      cnxn: connection to SQL database.
      path_list: list of component path prefixes.
      exact: set to False to include all components which have one of the
          given paths as their ancestor, instead of exact matches.

    Returns:
      A list of component IDs of component's whose paths match path_list.
    """
    or_terms = []
    args = []
    for path in path_list:
      or_terms.append('path = %s')
      args.append(path)

    if not exact:
      for path in path_list:
        or_terms.append('path LIKE %s')
        args.append(path + '>%')

    cond_str = '(' + ' OR '.join(or_terms) + ')'
    rows = self.componentdef_tbl.Select(
        cnxn, cols=['id'], where=[(cond_str, args)])
    return [row[0] for row in rows]

  def CreateComponentDef(
      self, cnxn, project_id, path, docstring, deprecated, admin_ids, cc_ids,
      created, creator_id, label_ids):
    """Create a new component definition with the given info.

    Args:
      cnxn: connection to SQL database.
      project_id: int ID of the current project.
      path: string pathname of the new component.
      docstring: string describing this field.
      deprecated: whether or not this should be autocompleted
      admin_ids: list of int IDs of users who can administer.
      cc_ids: list of int IDs of users to notify when an issue in
          this component is updated.
      created: timestamp this component was created at.
      creator_id: int ID of user who created this component.
      label_ids: list of int IDs of labels to add when an issue is
          in this component.

    Returns:
      Integer component_id of the new component definition.
    """
    component_id = self.componentdef_tbl.InsertRow(
        cnxn, project_id=project_id, path=path, docstring=docstring,
        deprecated=deprecated, created=created, creator_id=creator_id,
        commit=False)
    self.component2admin_tbl.InsertRows(
        cnxn, COMPONENT2ADMIN_COLS,
        [(component_id, admin_id) for admin_id in admin_ids],
        commit=False)
    self.component2cc_tbl.InsertRows(
        cnxn, COMPONENT2CC_COLS,
        [(component_id, cc_id) for cc_id in cc_ids],
        commit=False)
    self.component2label_tbl.InsertRows(
        cnxn, COMPONENT2LABEL_COLS,
        [(component_id, label_id) for label_id in label_ids],
        commit=False)
    cnxn.Commit()
    self.config_2lc.InvalidateKeys(cnxn, [project_id])
    self.InvalidateMemcacheForEntireProject(project_id)
    return component_id

  def UpdateComponentDef(
      self, cnxn, project_id, component_id, path=None, docstring=None,
      deprecated=None, admin_ids=None, cc_ids=None, created=None,
      creator_id=None, modified=None, modifier_id=None,
      label_ids=None):
    """Update the specified component definition."""
    new_values = {}
    if path is not None:
      assert path
      new_values['path'] = path
    if docstring is not None:
      new_values['docstring'] = docstring
    if deprecated is not None:
      new_values['deprecated'] = deprecated
    if created is not None:
      new_values['created'] = created
    if creator_id is not None:
      new_values['creator_id'] = creator_id
    if modified is not None:
      new_values['modified'] = modified
    if modifier_id is not None:
      new_values['modifier_id'] = modifier_id

    if admin_ids is not None:
      self.component2admin_tbl.Delete(
          cnxn, component_id=component_id, commit=False)
      self.component2admin_tbl.InsertRows(
          cnxn, COMPONENT2ADMIN_COLS,
          [(component_id, admin_id) for admin_id in admin_ids],
          commit=False)

    if cc_ids is not None:
      self.component2cc_tbl.Delete(
          cnxn, component_id=component_id, commit=False)
      self.component2cc_tbl.InsertRows(
          cnxn, COMPONENT2CC_COLS,
          [(component_id, cc_id) for cc_id in cc_ids],
          commit=False)

    if label_ids is not None:
      self.component2label_tbl.Delete(
          cnxn, component_id=component_id, commit=False)
      self.component2label_tbl.InsertRows(
          cnxn, COMPONENT2LABEL_COLS,
          [(component_id, label_id) for label_id in label_ids],
          commit=False)

    self.componentdef_tbl.Update(
        cnxn, new_values, id=component_id, commit=False)
    cnxn.Commit()
    self.config_2lc.InvalidateKeys(cnxn, [project_id])
    self.InvalidateMemcacheForEntireProject(project_id)

  def DeleteComponentDef(self, cnxn, project_id, component_id):
    """Delete the specified component definition."""
    self.componentdef_tbl.Update(
        cnxn, {'is_deleted': True}, id=component_id, commit=False)

    cnxn.Commit()
    self.config_2lc.InvalidateKeys(cnxn, [project_id])
    self.InvalidateMemcacheForEntireProject(project_id)

  ### Memcache management

  def InvalidateMemcache(self, issues, key_prefix=''):
    """Delete the memcache entries for issues and their project-shard pairs."""
    memcache.delete_multi(
        [str(issue.issue_id) for issue in issues], key_prefix='issue:',
        seconds=5, namespace=settings.memcache_namespace)
    project_shards = set(
        (issue.project_id, issue.issue_id % settings.num_logical_shards)
        for issue in issues)
    self._InvalidateMemcacheShards(project_shards, key_prefix=key_prefix)

  def _InvalidateMemcacheShards(self, project_shards, key_prefix=''):
    """Delete the memcache entries for the given project-shard pairs.

    Deleting these rows does not delete the actual cached search results
    but it does mean that they will be considered stale and thus not used.

    Args:
      project_shards: list of (pid, sid) pairs.
      key_prefix: string to pass as memcache key prefix.
    """
    cache_entries = ['%d;%d' % ps for ps in project_shards]
    # Whenever any project is invalidated, also invalidate the 'all'
    # entry that is used in site-wide searches.
    shard_id_set = {sid for _pid, sid in project_shards}
    cache_entries.extend(('all;%d' % sid) for sid in shard_id_set)

    memcache.delete_multi(
        cache_entries, key_prefix=key_prefix,
        namespace=settings.memcache_namespace)

  def InvalidateMemcacheForEntireProject(self, project_id):
    """Delete the memcache entries for all searches in a project."""
    project_shards = set((project_id, shard_id)
                         for shard_id in range(settings.num_logical_shards))
    self._InvalidateMemcacheShards(project_shards)
    memcache.delete_multi(
        [str(project_id)], key_prefix='config:',
        namespace=settings.memcache_namespace)
    memcache.delete_multi(
        [str(project_id)], key_prefix='label_rows:',
        namespace=settings.memcache_namespace)
    memcache.delete_multi(
        [str(project_id)], key_prefix='status_rows:',
        namespace=settings.memcache_namespace)
    memcache.delete_multi(
        [str(project_id)], key_prefix='field_rows:',
        namespace=settings.memcache_namespace)

  def UsersInvolvedInConfig(self, config, project_templates):
    """Return a set of all user IDs referenced in the ProjectIssueConfig."""
    result = set()
    for template in project_templates:
      result.update(tracker_bizobj.UsersInvolvedInTemplate(template))
    for field in config.field_defs:
      result.update(field.admin_ids)
      result.update(field.editor_ids)
    # TODO(jrobbins): add component owners, auto-cc, and admins.
    return result
