static int mdbDeleteRow(Edi *edi, cchar *tableName, cchar *key) { Mdb *mdb; MdbTable *table; int r, rc; mprAssert(edi); mprAssert(tableName && *tableName); mprAssert(key && *key); mdb = (Mdb*) edi; lock(mdb); if ((table = lookupTable(mdb, tableName)) == 0) { unlock(mdb); return MPR_ERR_CANT_FIND; } if ((r = lookupRow(table, key)) < 0) { unlock(mdb); return MPR_ERR_CANT_FIND; } rc = mprRemoveItemAtPos(table->rows, r); if (table->index) { mprRemoveKey(table->index, key); } autoSave(mdb, table); unlock(mdb); return rc; }
static int deleteXmlPropertyByName(Ejs *ejs, EjsXML *xml, EjsName qname) { EjsXML *item; bool removed; int next; removed = 0; if (qname.name->value[0] == '@') { /* @ and @* */ if (xml->attributes) { for (next = 0; (item = mprGetNextItem(xml->attributes, &next)) != 0; ) { assert(qname.name->value[0] == '@'); if (qname.name->value[1] == '*' || wcmp(item->qname.name->value, &qname.name->value[1]) == 0) { mprRemoveItemAtPos(xml->attributes, next - 1); item->parent = 0; removed = 1; next -= 1; } } } } else { /* name and * */ if (xml->elements) { for (next = 0; (item = mprGetNextItem(xml->elements, &next)) != 0; ) { assert(item->qname.name); if (qname.name->value[0] == '*' || ejsCompareString(ejs, item->qname.name, qname.name) == 0) { mprRemoveItemAtPos(xml->elements, next - 1); item->parent = 0; removed = 1; next -= 1; } } } } return (removed) ? 0 : EJS_ERR; }
/* Set a property by name There are 7 kinds of qname's: prop, @att, [prop], *, @*, .name, .@name */ static int setXmlPropertyByName(Ejs *ejs, EjsXML *xml, EjsName qname, EjsObj *value) { EjsXML *elt, *xvalue, *rp, *lastElt; EjsObj *originalValue; int index, last; last = 0; lastElt = 0; if (isdigit((uchar) qname.name->value[0]) && allDigitsForXml(qname.name)) { ejsThrowTypeError(ejs, "Integer indicies for set are not allowed"); return EJS_ERR; } if (xml->kind != EJS_XML_ELEMENT) { // TODO spec requires this -- but why? -- surely throw? return 0; } /* Massage the value type. */ originalValue = value; xvalue = (EjsXML*) value; if (ejsIsXML(ejs, xvalue)) { if (xvalue->kind == EJS_XML_LIST) { value = cloneXml(ejs, xvalue, 1); } else if (xvalue->kind == EJS_XML_TEXT || xvalue->kind == EJS_XML_ATTRIBUTE) { value = ejsCast(ejs, originalValue, String); } else { value = cloneXml(ejs, xvalue, 1); } } else { value = ejsCast(ejs, value, String); } if (qname.name->value[0] == '@') { return setXmlPropertyAttributeByName(ejs, xml, qname, value); } /* Delete redundant elements by the same name. */ if (xml->elements) { for (last = -1, index = -1; (elt = mprGetPrevItem(xml->elements, &index)) != 0; ) { if (qname.name->value[0] == '*' || (elt->kind == EJS_XML_ELEMENT && elt->qname.name == qname.name)) { /* Must remove all redundant elements of the same name except the first one */ if (last >= 0) { rp = mprGetItem(xml->elements, last); rp->parent = 0; mprRemoveItemAtPos(xml->elements, last); } last = index; lastElt = elt; } } } if (xml->elements == 0) { // TODO - need routine to do this centrally so we can control the default number of elements in the list? xml->elements = mprCreateList(-1, 0); } elt = lastElt; index = last; if (qname.name->value[0] == '*') { /* Special case when called from XMLList to update the value of an element */ xml = createValueNode(ejs, xml, value); } else if (elt == 0) { /* Not found. New node required. */ elt = ejsCreateXML(ejs, EJS_XML_ELEMENT, qname, xml, NULL); if (elt == 0) { return 0; } index = mprGetListLength(xml->elements); xml = ejsAppendToXML(ejs, xml, createValueNode(ejs, elt, value)); } else { /* Update existing element. */ xml = ejsSetXMLElement(ejs, xml, index, createValueNode(ejs, elt, value)); } if (xml == 0) { return EJS_ERR; } return index; }
/* Set a property attribute by name. */ static int setXmlPropertyAttributeByName(Ejs *ejs, EjsXML *xml, EjsName qname, EjsObj *value) { EjsXML *elt, *attribute, *xvalue, *lastElt; EjsString *sv; EjsName qn; wchar *str; int index, last, next; /* Attribute. If the value is an XML list, convert to a space separated string */ xvalue = (EjsXML*) value; if (ejsIsXML(ejs, xvalue) && xvalue->kind == EJS_XML_LIST) { str = 0; for (next = 0; (elt = mprGetNextItem(xvalue->elements, &next)) != 0; ) { sv = (EjsString*) ejsCast(ejs, (EjsObj*) elt, String); str = mrejoin(str, NULL, " ", sv->value, NULL); } value = (EjsObj*) ejsCreateString(ejs, str, -1); } else { value = ejsCast(ejs, value, String); } assert(ejsIs(ejs, value, String)); /* Find the first attribute that matches. Delete all other attributes of the same name. */ index = 0; if (xml->attributes) { lastElt = 0; for (last = -1, index = -1; (elt = mprGetPrevItem(xml->attributes, &index)) != 0; ) { assert(qname.name->value[0] == '@'); if (wcmp(elt->qname.name->value, &qname.name->value[1]) == 0) { if (last >= 0) { mprRemoveItemAtPos(xml->attributes, last); } last = index; lastElt = elt; } } if (lastElt) { /* Found a match. So replace its value */ lastElt->value = (EjsString*) value; return last; } else { index = mprGetListLength(xml->attributes); } } // TODO - namespace work to do here /* Not found. Create a new attribute node */ assert(ejsIs(ejs, value, String)); qn.space = NULL; qn.name = ejsSubstring(ejs, qname.name, 1, -1); attribute = ejsCreateXML(ejs, EJS_XML_ATTRIBUTE, qn, xml, (EjsString*) value); if (xml->attributes == 0) { xml->attributes = mprCreateList(-1, 0); } mprSetItem(xml->attributes, index, attribute); return index; }