static bool NameInUsingClause(IdList using_, string colName) { if (using_ != null) for (int k = 0; k < using_.Ids.length; k++) if (string.Compare(using_.Ids[k].Name, colName, StringComparison.OrdinalIgnoreCase) == 0) return true; return false; }
/* ** pEList is the SET clause of an UPDATE statement. Each entry ** in pEList is of the format <id>=<expr>. If any of the entries ** in pEList have an <id> which matches an identifier in pIdList, ** then return TRUE. If pIdList==NULL, then it is considered a ** wildcard that matches anything. Likewise if pEList==NULL then ** it matches anything so always return true. Return false only ** if there is no match. */ static int checkColumnOverlap(IdList pIdList, ExprList pEList) { int e; if (pIdList == null || NEVER(pEList == null)) return 1; for (e = 0; e < pEList.nExpr; e++) { if (sqlite3IdListIndex(pIdList, pEList.a[e].zName) >= 0) return 1; } return 0; }
public static void RenderResults(HtmlWriter writer, SearchRecord[] records, bool renderUl = true) { var visibleCategorizations = CategorizationFolder.GetVisibleCategorizations(); var newsListUrl = Urls.GetMainNewsListUrl(); if (renderUl) writer.RenderBeginTag(HtmlTextWriterTag.Ul, "news-list"); foreach (var record in records) { var date = record.GetDate("date"); writer.RenderBeginTag(HtmlTextWriterTag.Li, "clearfix"); writer.RenderBeginTag(HtmlTextWriterTag.Div); writer.AddAttribute(HtmlTextWriterAttribute.Href, record.GetString("url")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.RenderFullTag(HtmlTextWriterTag.H3, record.GetString("title")); writer.RenderEndTag(); // a if (date != null) writer.RenderFullTag(HtmlTextWriterTag.Span, "Publiseret " + record.GetDate("date").Value.ToString("dd-MM-yyyy"), "date"); var categorizations = new IdList(record.GetString("categorizations")); if (categorizations.Any()) { RenderCategorizations(writer, categorizations, visibleCategorizations, newsListUrl); } writer.RenderBeginTag(HtmlTextWriterTag.A); var text = record.GetString("summary"); if (text.Length > 150) text = text.Substring(0, 150); writer.RenderFullTag(HtmlTextWriterTag.P, text); writer.RenderEndTag(); // a writer.RenderEndTag(); // div writer.RenderEndTag(); // li.clearfix } if (renderUl) writer.RenderEndTag(); }
protected void Page_Load(object sender, EventArgs e) { AjaxUtil.RegisterPageMethods(this); if (!string.IsNullOrEmpty(Request.QueryString["frame"])) { ClientScript.RegisterStartupScript(Page.GetType(), "editorInitialization", @" var gridEditorFrame = $('#" + Request.QueryString["frame"] + @"', window.parent.document); gridEditorFrame.parent().css('clear','both'); ", true); } editor.Attributes.Add("hiddenId", Request.QueryString["hiddenId"]); var provider = GetProvider(); var sourceNodes = provider.GetRootNodes().ToList(); var destinationNodes = new List<Node>(); using (CmsContext.Editing) { var item = CmsService.Instance.GetItem<Entity>(new Id(Request.QueryString["itemId"])); var fieldName = Request.QueryString["fieldName"]; var value = new IdList(item[fieldName]); foreach (var id in value) { var node = sourceNodes.Where(n => n.Id == id.ToString()).FirstOrDefault(); if (node != null) { sourceNodes.Remove(node); destinationNodes.Add(node); } } var litSource = new Literal(); litSource.Text = "<ul class=\"srcList listbox\">" + multiListControl.GenerateListBox(sourceNodes) + "</ul>"; multiListControl.Initialize(litSource, destinationNodes); } }
protected override void CreateChildControls() { var provider = GetProvider(); using (CmsContext.Editing) { var item = CmsService.Instance.GetItem<Entity>(new Id(Request.QueryString["itemId"])); var fieldName = Request.QueryString["fieldName"]; var value = new IdList(item[fieldName]); var destinationNodes = value.Select(id => provider.GetNode(id.ToString())).Where(node => node != null).ToArray(); var treeview = new LinqItTreeView(); treeview.Provider = Request.QueryString["provider"]; treeview.ProviderReferenceId = Request.QueryString["itemId"]; var placeholder = new PlaceHolder(); placeholder.Controls.Add(new LiteralControl("<div class=\"srcList \">")); placeholder.Controls.Add(treeview); placeholder.Controls.Add(new LiteralControl("</div>")); multiListControl.Initialize(placeholder, destinationNodes); } base.CreateChildControls(); }
/// <summary> /// Creates an XmlElement representing an Epi Info 7 view's data. /// </summary> /// <param name="xmlDataPackage">The data package xml document that the XmlElement should be added to</param> /// <param name="form">The form whose data will be serialized</param> /// <returns>XmlElement; represents the form's data in Xml format, suitable for use in data packaging</returns> protected override XmlElement CreateXmlFormDataElement(XmlDocument xmlDataPackage, View form) { #region Input Validation if (xmlDataPackage == null) { throw new ArgumentNullException("xmlDataPackage"); } if (form == null) { throw new ArgumentNullException("form"); } #endregion // Input Validation XmlElement data = xmlDataPackage.CreateElement("Data"); OnStatusChanged(String.Format("Packaging data for form {0}...", form.Name)); OnResetProgress(); /* This seems like an usual set of steps to just iterate over the data. The problem is that we can't "just * iterate over the data" - the data is split up page tables, with one table representing one page on the * form. While a JOIN might be able to bring everything together into one table, it might not - for example, * if there are >255 fields after the JOIN, an OleDb exception will be thrown. * * To get around this issue: The code first iterates over the rows in the BASE TABLE, obtaining the GUID * values for each. The GUIDs and their corresponding XmlElement go into a dictionary. * * Later, each row in each page is iterated over; as the GUIDs for each page table are accessed, the corresponding * XmlElement is pulled from the dictionary. Field data is added to it for each field that has data. In this * manner, it doesn't matter that each row is technically accessed out-of-order because they'll still show up * in-order in the resulting Xml. * * Filtering adds another layer of complexity. To filter, a JOIN operation is needed so that the filters can * be applied across all those tables, since the fields in the filter may be across different tables. The * RowFilter class provides a way to handle this; we simply get the query from that object and apply it to the * reader. Only GUIDs that match the filter are added to the dictionary of guids. */ // We need to exclude records from child forms that may now be orphaned as a result of a filter applied to the parent if (form.IsRelatedView && PreviousDistanceFromRoot < CurrentDistanceFromRoot) { ParentIdList.Clear(); foreach (KeyValuePair <string, XmlElement> kvp in IdList) { ParentIdList.Add(kvp.Key); } } IdList.Clear(); // Very important, this needs to be re-set in case we've already processed a form (this is a class level variable) if (!ExportInfo.RecordsPackaged.ContainsKey(form)) { ExportInfo.RecordsPackaged.Add(form, 0); } //bool filterThisForm = false; RowFilters filters = null; Query selectQuery = null; IDbDriver db = SourceProject.CollectedData.GetDatabase(); string recStatusClause = String.Empty; if (Filters != null && Filters.ContainsKey(form.Name) && Filters[form.Name].Count() > 0) { //filterThisForm = true; filters = Filters[form.Name]; filters.RecordProcessingScope = RecordProcessingScope; selectQuery = filters.GetGuidSelectQuery(form); List <QueryParameter> paramsToAdd = selectQuery.Parameters; selectQuery = db.CreateQuery(selectQuery.SqlStatement.Replace("[t].[GlobalRecordId], [t].[FKEY], [t].[RECSTATUS]", "*")); selectQuery.Parameters = paramsToAdd; } else { recStatusClause = "RECSTATUS = 1"; if (RecordProcessingScope == Epi.RecordProcessingScope.Both) { recStatusClause = "RECSTATUS >= 0"; } else if (RecordProcessingScope == Epi.RecordProcessingScope.Deleted) { recStatusClause = "RECSTATUS = 0"; } string selectQueryText = "SELECT * " + form.FromViewSQL; selectQueryText = "SELECT * " + form.FromViewSQL + " WHERE " + recStatusClause; selectQuery = db.CreateQuery(selectQueryText); } double totalRecords = Convert.ToDouble(db.ExecuteScalar(db.CreateQuery("SELECT COUNT(*) FROM " + form.TableName))); var fieldInclusionList = new List <RenderableField>(); foreach (Field field in form.Fields) { if (field is IDataField && field is RenderableField && !(field is GridField) && !(FieldsToNull.ContainsKey(form.Name) && FieldsToNull[form.Name].Contains(field.Name))) { var fieldToAdd = field as RenderableField; if (fieldToAdd != null) { fieldInclusionList.Add(fieldToAdd); } } } int processedRecords = 0; //using (IDataReader guidReader = db.ExecuteReader(selectQuery)) //using (IDataReader guidReader = filterThisForm ? db.ExecuteReader(selectQuery) : db.GetTableDataReader(form.TableName)) DataTable fullTable = db.Select(selectQuery); //int lowKey = (int)db.ExecuteScalar(db.CreateQuery("SELECT Min(UniqueKey) FROM " + form.TableName)); //int highKey = (int)db.ExecuteScalar(db.CreateQuery("SELECT Max(UniqueKey) FROM " + form.TableName)); ////ProcessRows(fullTable.Select("UniqueKey >= " + lowKey + " AND UniqueKey <= " + (highKey / 4)), form, xmlDataPackage, fieldInclusionList); string set1 = String.Empty; //string set2 = String.Empty; //string set3 = String.Empty; //string set4 = String.Empty; //Parallel.Invoke( // () => // { set1 = ProcessRows(fullTable.Rows, form, xmlDataPackage, fieldInclusionList); //}, //() => //{ // set2 = ProcessRows(fullTable.Select("UniqueKey >= " + (highKey / 4) + " AND UniqueKey < " + (highKey / 2)), form, xmlDataPackage, fieldInclusionList); //}, //() => //{ // set3 = ProcessRows(fullTable.Select("UniqueKey >= " + (highKey / 2) + " AND UniqueKey < " + (highKey / 1.5)), form, xmlDataPackage, fieldInclusionList); //}, //() => //{ // set4 = ProcessRows(fullTable.Select("UniqueKey >= " + (highKey / 1.5) + " AND UniqueKey <= " + highKey), form, xmlDataPackage, fieldInclusionList); //} //); //StringBuilder sb = new StringBuilder(); //foreach (XmlElement element in set1) //{ // sb.Append(element.OuterXml); // //data.AppendChild(element); //} //foreach (XmlElement element in set2) //{ // sb.Append(element.OuterXml); // //data.AppendChild(element); //} //foreach (XmlElement element in set3) //{ // sb.Append(element.OuterXml); // //data.AppendChild(element); //} //foreach (XmlElement element in set4) //{ // sb.Append(element.OuterXml); // //data.AppendChild(element); //} data.InnerText = set1; return(data); foreach (DataRow guidReader in fullTable.Rows) { //using(var conn = new System.Data.SqlClient.SqlConnection(db.ConnectionString + ";Connection Timeout=10")) //{ // conn.Open(); // using (var selectCommand = new System.Data.SqlClient.SqlCommand(selectQueryText, conn)) // { // using (var guidReader = selectCommand.ExecuteReader()) // { // while (guidReader.Read()) // { string guid = guidReader["GlobalRecordId"].ToString();// guidReader.GetString(0); // guidReader["GlobalRecordId"].ToString(); string fkey = guidReader["FKEY"].ToString(); string recstatus = guidReader["RECSTATUS"].ToString(); string firstSaveUserId = String.Empty; DateTime?firstSaveTime = null; string lastSaveUserId = String.Empty; DateTime?lastSaveTime = null; firstSaveUserId = guidReader["FirstSaveLogonName"].ToString(); if (guidReader["FirstSaveTime"] != DBNull.Value) { firstSaveTime = (DateTime)guidReader["FirstSaveTime"]; } lastSaveUserId = guidReader["LastSaveLogonName"].ToString(); if (guidReader["LastSaveTime"] != DBNull.Value) { lastSaveTime = (DateTime)guidReader["LastSaveTime"]; } if (!form.IsRelatedView || ParentIdList.Contains(fkey)) { XmlElement record = xmlDataPackage.CreateElement("Record"); XmlAttribute id = xmlDataPackage.CreateAttribute("Id"); id.Value = guid; record.Attributes.Append(id); if (!string.IsNullOrEmpty(fkey)) { XmlAttribute foreignKey = xmlDataPackage.CreateAttribute("Fkey"); foreignKey.Value = fkey; record.Attributes.Append(foreignKey); } if (!string.IsNullOrEmpty(firstSaveUserId)) { XmlAttribute firstSaveId = xmlDataPackage.CreateAttribute("FirstSaveUserId"); firstSaveId.Value = firstSaveUserId; record.Attributes.Append(firstSaveId); } if (!string.IsNullOrEmpty(lastSaveUserId)) { XmlAttribute lastSaveId = xmlDataPackage.CreateAttribute("LastSaveUserId"); lastSaveId.Value = lastSaveUserId; record.Attributes.Append(lastSaveId); } if (firstSaveTime.HasValue) { XmlAttribute firstSaveDateTime = xmlDataPackage.CreateAttribute("FirstSaveTime"); firstSaveDateTime.Value = firstSaveTime.Value.Ticks.ToString(); record.Attributes.Append(firstSaveDateTime); } if (lastSaveTime.HasValue) { XmlAttribute lastSaveDateTime = xmlDataPackage.CreateAttribute("LastSaveTime"); lastSaveDateTime.Value = lastSaveTime.Value.Ticks.ToString(); record.Attributes.Append(lastSaveDateTime); } if (!String.IsNullOrEmpty(recstatus)) { XmlAttribute recStatusAttribute = xmlDataPackage.CreateAttribute("RecStatus"); recStatusAttribute.Value = recstatus; record.Attributes.Append(recStatusAttribute); } IdList.Add(guid, record); ExportInfo.TotalRecordsPackaged++; ExportInfo.RecordsPackaged[form]++; foreach (RenderableField field in fieldInclusionList) { XmlElement fieldData = xmlDataPackage.CreateElement("Field"); XmlAttribute name = xmlDataPackage.CreateAttribute("Name"); name.Value = field.Name; fieldData.Attributes.Append(name); string value = guidReader[field.Name].ToString(); if (!String.IsNullOrEmpty(value)) { if (field is DateTimeField) { DateTime dt = Convert.ToDateTime(value); fieldData.InnerText = dt.Ticks.ToString(); } else if (field is ImageField) { value = Convert.ToBase64String((Byte[])guidReader[field.Name]); fieldData.InnerText = value; } else if (field is NumberField) { value = Convert.ToDouble(value).ToString(System.Globalization.CultureInfo.InvariantCulture); fieldData.InnerText = value; } else { fieldData.InnerText = value; } } if (String.IsNullOrEmpty(fieldData.InnerText) && IncludeNullFieldData == false) { // do nothing, for now... } else { record.AppendChild(fieldData); } data.AppendChild(record); } } processedRecords++; double progress = (((double)processedRecords) / ((double)totalRecords)) * 100; OnProgressChanged(progress); } foreach (GridField gridField in form.Fields.GridFields) { data.AppendChild(CreateXmlGridElement(xmlDataPackage, form, gridField)); ExportInfo.GridsProcessed++; } return(data); }
static TriggerStep sqlite3TriggerInsertStep( sqlite3 db, Token pTableName, IdList pColumn, int null_4, Select pSelect, u8 orconf ) { return sqlite3TriggerInsertStep( db, pTableName, pColumn, null, pSelect, orconf ); }
/* ** This is called by the parser when it sees a CREATE TRIGGER statement ** up to the point of the BEGIN before the trigger actions. A Trigger ** structure is generated based on the information available and stored ** in pParse.pNewTrigger. After the trigger actions have been parsed, the ** sqlite3FinishTrigger() function is called to complete the trigger ** construction process. */ static void sqlite3BeginTrigger( Parse pParse, /* The parse context of the CREATE TRIGGER statement */ Token pName1, /* The name of the trigger */ Token pName2, /* The name of the trigger */ int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ IdList pColumns, /* column list if this is an UPDATE OF trigger */ SrcList pTableName,/* The name of the table/view the trigger applies to */ Expr pWhen, /* WHEN clause */ int isTemp, /* True if the TEMPORARY keyword is present */ int noErr /* Suppress errors if the trigger already exists */ ) { Trigger pTrigger = null; /* The new trigger */ Table pTab; /* Table that the trigger fires off of */ string zName = null; /* Name of the trigger */ sqlite3 db = pParse.db; /* The database connection */ int iDb; /* The database to store the trigger in */ Token pName = null; /* The unqualified db name */ DbFixer sFix = new DbFixer(); /* State vector for the DB fixer */ int iTabDb; /* Index of the database holding pTab */ Debug.Assert( pName1 != null ); /* pName1.z might be NULL, but not pName1 itself */ Debug.Assert( pName2 != null ); Debug.Assert( op == TK_INSERT || op == TK_UPDATE || op == TK_DELETE ); Debug.Assert( op > 0 && op < 0xff ); if ( isTemp != 0 ) { /* If TEMP was specified, then the trigger name may not be qualified. */ if ( pName2.n > 0 ) { sqlite3ErrorMsg( pParse, "temporary trigger may not have qualified name" ); goto trigger_cleanup; } iDb = 1; pName = pName1; } else { /* Figure out the db that the the trigger will be created in */ iDb = sqlite3TwoPartName( pParse, pName1, pName2, ref pName ); if ( iDb < 0 ) { goto trigger_cleanup; } } if ( null == pTableName ) //|| db.mallocFailed { goto trigger_cleanup; } /* A long-standing parser bug is that this syntax was allowed: ** ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab .... ** ^^^^^^^^ ** ** To maintain backwards compatibility, ignore the database ** name on pTableName if we are reparsing our of SQLITE_MASTER. */ if ( db.init.busy != 0 && iDb != 1 ) { //sqlite3DbFree( db, pTableName.a[0].zDatabase ); pTableName.a[0].zDatabase = null; } /* If the trigger name was unqualified, and the table is a temp table, ** then set iDb to 1 to create the trigger in the temporary database. ** If sqlite3SrcListLookup() returns 0, indicating the table does not ** exist, the error is caught by the block below. */ if ( pTableName == null /*|| db.mallocFailed != 0 */ ) { goto trigger_cleanup; } pTab = sqlite3SrcListLookup( pParse, pTableName ); if ( db.init.busy == 0 && pName2.n == 0 && pTab != null && pTab.pSchema == db.aDb[1].pSchema ) { iDb = 1; } /* Ensure the table name matches database name and that the table exists */ // if ( db.mallocFailed != 0 ) goto trigger_cleanup; Debug.Assert( pTableName.nSrc == 1 ); if ( sqlite3FixInit( sFix, pParse, iDb, "trigger", pName ) != 0 && sqlite3FixSrcList( sFix, pTableName ) != 0 ) { goto trigger_cleanup; } pTab = sqlite3SrcListLookup( pParse, pTableName ); if ( pTab == null ) { /* The table does not exist. */ if ( db.init.iDb == 1 ) { /* Ticket #3810. ** Normally, whenever a table is dropped, all associated triggers are ** dropped too. But if a TEMP trigger is created on a non-TEMP table ** and the table is dropped by a different database connection, the ** trigger is not visible to the database connection that does the ** drop so the trigger cannot be dropped. This results in an ** "orphaned trigger" - a trigger whose associated table is missing. */ db.init.orphanTrigger = 1; } goto trigger_cleanup; } if ( IsVirtual( pTab ) ) { sqlite3ErrorMsg( pParse, "cannot create triggers on virtual tables" ); goto trigger_cleanup; } /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ zName = sqlite3NameFromToken( db, pName ); if ( zName == null || SQLITE_OK != sqlite3CheckObjectName( pParse, zName ) ) { goto trigger_cleanup; } Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) ); if ( sqlite3HashFind( ( db.aDb[iDb].pSchema.trigHash ), zName, sqlite3Strlen30( zName ), (Trigger)null ) != null ) { if ( noErr == 0 ) { sqlite3ErrorMsg( pParse, "trigger %T already exists", pName ); } else { Debug.Assert( 0==db.init.busy ); sqlite3CodeVerifySchema( pParse, iDb ); } goto trigger_cleanup; } /* Do not create a trigger on a system table */ if ( pTab.zName.StartsWith( "sqlite_", System.StringComparison.InvariantCultureIgnoreCase ) ) { sqlite3ErrorMsg( pParse, "cannot create trigger on system table" ); pParse.nErr++; goto trigger_cleanup; } /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. */ if ( pTab.pSelect != null && tr_tm != TK_INSTEAD ) { sqlite3ErrorMsg( pParse, "cannot create %s trigger on view: %S", ( tr_tm == TK_BEFORE ) ? "BEFORE" : "AFTER", pTableName, 0 ); goto trigger_cleanup; } if ( pTab.pSelect == null && tr_tm == TK_INSTEAD ) { sqlite3ErrorMsg( pParse, "cannot create INSTEAD OF" + " trigger on table: %S", pTableName, 0 ); goto trigger_cleanup; } iTabDb = sqlite3SchemaToIndex( db, pTab.pSchema ); #if !SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_CREATE_TRIGGER; string zDb = db.aDb[iTabDb].zName; string zDbTrig = isTemp ? db.aDb[1].zName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab.zName, zDbTrig) ){ goto trigger_cleanup; } if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ goto trigger_cleanup; } } #endif /* INSTEAD OF triggers can only appear on views and BEFORE triggers ** cannot appear on views. So we might as well translate every ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code ** elsewhere. */ if ( tr_tm == TK_INSTEAD ) { tr_tm = TK_BEFORE; } /* Build the Trigger object */ pTrigger = new Trigger();// (Trigger*)sqlite3DbMallocZero( db, sizeof(Trigger )) if ( pTrigger == null ) goto trigger_cleanup; pTrigger.zName = zName; pTrigger.table = pTableName.a[0].zName;// sqlite3DbStrDup( db, pTableName.a[0].zName ); pTrigger.pSchema = db.aDb[iDb].pSchema; pTrigger.pTabSchema = pTab.pSchema; pTrigger.op = (u8)op; pTrigger.tr_tm = tr_tm == TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger.pWhen = sqlite3ExprDup( db, pWhen, EXPRDUP_REDUCE ); pTrigger.pColumns = sqlite3IdListDup( db, pColumns ); Debug.Assert( pParse.pNewTrigger == null ); pParse.pNewTrigger = pTrigger; trigger_cleanup: sqlite3DbFree( db, ref zName ); sqlite3SrcListDelete( db, ref pTableName ); sqlite3IdListDelete( db, ref pColumns ); sqlite3ExprDelete( db, ref pWhen ); if ( pParse.pNewTrigger == null ) { sqlite3DeleteTrigger( db, ref pTrigger ); } else { Debug.Assert( pParse.pNewTrigger == pTrigger ); } }
static string Example5() { NamedReg x1 = new NamedReg(); x1.name = "x1"; NamedReg x2 = new NamedReg(); x2.name = "x2"; IdList idl1 = new IdList(); idl1.Add(x1); idl1.Add(x2); LocalDecl ld1 = new LocalDecl(); ld1.type = new NumType(); ld1.id_list = idl1; AtomExprList ael1 = new AtomExprList(); ael1.Add(x1); ael1.Add(x2); ReturnStmt rs1 = new ReturnStmt(); rs1.rv = ael1; StmtList sl1 = new StmtList(); sl1.Add(ld1); sl1.Add(rs1); Sub abc = new Sub("abc", sl1); Pirate p = new Pirate(); p.Add(abc); StringWriter sw = new StringWriter(); PirateWriter pv = new PirateWriter(sw); DynamicVisitor.accept(p, pv); return sw.ToString(); }
static string Example3() { Pirate p = new Pirate(); StmtList sl1 = new StmtList(); Sub joe = new Sub("joe", sl1); p.Add(joe); LocalDecl ld1 = new LocalDecl(); ld1.type = new StringType(); NamedReg name = new NamedReg(); name.name = "name"; IdList idl1 = new IdList(); idl1.Add(name); ld1.id_list = idl1; sl1.Add(ld1); Assign a1 = new Assign(); a1.lval = name; StringLiteral s1 = new StringLiteral(); s1.value = " Joe!"; a1.rval = s1; sl1.Add(a1); Assign a2 = new Assign(); StringLiteral s2 = new StringLiteral(); s2.value = "Hi!"; TmpStringReg tsr0 = new TmpStringReg(); tsr0.number = 0; a2.lval = tsr0; a2.rval = s2; sl1.Add(a2); Assign a3 = new Assign(); TmpStringReg tsr1 = new TmpStringReg(); tsr1.number = 1; BinaryCat bc1 = new BinaryCat(); bc1.a = tsr0; bc1.b = name; a3.lval = tsr1; a3.rval = bc1; sl1.Add(a3); AssignCat a4 = new AssignCat(); a4.lval = tsr1; StringLiteral s3 = new StringLiteral(); s3.value = "\n"; a4.rval = s3; sl1.Add(a4); CallStmt cs1 = new CallStmt(); Call c1 = new Call(); c1.func = "print"; c1.args = tsr1; cs1.call = c1; sl1.Add(cs1); StringWriter sw = new StringWriter(); PirateWriter pv = new PirateWriter(sw); DynamicVisitor.accept(p, pv); return sw.ToString(); }
static void sqlite3Insert( Parse pParse, /* Parser context */ SrcList pTabList, /* Name of table into which we are inserting */ ExprList pList, /* List of values to be inserted */ Select pSelect, /* A SELECT statement to use as the data source */ IdList pColumn, /* Column names corresponding to IDLIST. */ int onError /* How to handle constraint errors */ ) { sqlite3 db; /* The main database structure */ Table pTab; /* The table to insert into. aka TABLE */ string zTab; /* Name of the table into which we are inserting */ string zDb; /* Name of the database holding this table */ int i = 0; int j = 0; int idx = 0; /* Loop counters */ Vdbe v; /* Generate code into this virtual machine */ Index pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ int baseCur = 0; /* VDBE VdbeCursor number for pTab */ int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ int endOfLoop = 0; /* Label for the end of the insertion loop */ bool useTempTable = false; /* Store SELECT results in intermediate table */ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ int addrInsTop = 0; /* Jump to label "D" */ int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ int addrSelect = 0; /* Address of coroutine that implements the SELECT */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int iDb; /* Index of database holding TABLE */ Db pDb; /* The database containing table being inserted into */ bool appendFlag = false; /* True if the insert is likely to be an append */ /* Register allocations */ int regFromSelect = 0; /* Base register for data coming from SELECT */ int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ int regRowCount = 0; /* Memory cell used for the row counter */ int regIns; /* Block of regs holding rowid+data being inserted */ int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ int regEof = 0; /* Register recording end of SELECT data */ int[] aRegIdx = null; /* One register allocated to each index */ #if !SQLITE_OMIT_TRIGGER bool isView = false; /* True if attempting to insert into a view */ Trigger pTrigger; /* List of triggers on pTab, if required */ int tmask = 0; /* Mask of trigger times */ #endif db = pParse.db; dest = new SelectDest();// memset( &dest, 0, sizeof( dest ) ); if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) { goto insert_cleanup; } /* Locate the table into which we will be inserting new information. */ Debug.Assert( pTabList.nSrc == 1 ); zTab = pTabList.a[0].zName; if ( NEVER( zTab == null ) ) goto insert_cleanup; pTab = sqlite3SrcListLookup( pParse, pTabList ); if ( pTab == null ) { goto insert_cleanup; } iDb = sqlite3SchemaToIndex( db, pTab.pSchema ); Debug.Assert( iDb < db.nDb ); pDb = db.aDb[iDb]; zDb = pDb.zName; #if NO_SQLITE_OMIT_AUTHORIZATION //#if !SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab.zName, 0, zDb) ){ goto insert_cleanup; } #endif /* Figure out if we have any triggers and if the table being ** inserted into is a view */ #if !SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist( pParse, pTab, TK_INSERT, null, out tmask ); isView = pTab.pSelect != null; #else Trigger pTrigger = null; //# define pTrigger 0 int tmask = 0; //# define tmask 0 bool isView = false; #endif #if SQLITE_OMIT_VIEW //# undef isView isView = false; #endif #if !SQLITE_OMIT_TRIGGER Debug.Assert( ( pTrigger != null && tmask != 0 ) || ( pTrigger == null && tmask == 0 ) ); #endif #if !SQLITE_OMIT_VIEW /* If pTab is really a view, make sure it has been initialized. ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual ** module table). */ if ( sqlite3ViewGetColumnNames( pParse, pTab ) != -0 ) { goto insert_cleanup; } #endif /* Ensure that: * (a) the table is not read-only, * (b) that if it is a view then ON INSERT triggers exist */ if ( sqlite3IsReadOnly( pParse, pTab, tmask ) ) { goto insert_cleanup; } /* Allocate a VDBE */ v = sqlite3GetVdbe( pParse ); if ( v == null ) goto insert_cleanup; if ( pParse.nested == 0 ) sqlite3VdbeCountChanges( v ); sqlite3BeginWriteOperation( pParse, ( pSelect != null || pTrigger != null ) ? 1 : 0, iDb ); #if !SQLITE_OMIT_XFER_OPT /* If the statement is of the form ** ** INSERT INTO <table1> SELECT * FROM <table2>; ** ** Then special optimizations can be applied that make the transfer ** very fast and which reduce fragmentation of indices. ** ** This is the 2nd template. */ if ( pColumn == null && xferOptimization( pParse, pTab, pSelect, onError, iDb ) != 0 ) { Debug.Assert( null == pTrigger ); Debug.Assert( pList == null ); goto insert_end; } #endif // * SQLITE_OMIT_XFER_OPT */ /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell regAutoinc. */ regAutoinc = autoIncBegin( pParse, iDb, pTab ); /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The ** co-routine is the common header to the 3rd and 4th templates. */ if ( pSelect != null ) { /* Data is coming from a SELECT. Generate code to implement that SELECT ** as a co-routine. The code is common to both the 3rd and 4th ** templates: ** ** EOF <- 0 ** X <- A ** goto B ** A: setup for the SELECT ** loop over the tables in the SELECT ** load value into register R..R+n ** yield X ** end loop ** cleanup after the SELECT ** EOF <- 1 ** yield X ** halt-error ** ** On each invocation of the co-routine, it puts a single row of the ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1. ** (These output registers are allocated by sqlite3Select().) When ** the SELECT completes, it sets the EOF flag stored in regEof. */ int rc = 0, j1; regEof = ++pParse.nMem; sqlite3VdbeAddOp2( v, OP_Integer, 0, regEof ); /* EOF <- 0 */ #if SQLITE_DEBUG VdbeComment( v, "SELECT eof flag" ); #endif sqlite3SelectDestInit( dest, SRT_Coroutine, ++pParse.nMem ); addrSelect = sqlite3VdbeCurrentAddr( v ) + 2; sqlite3VdbeAddOp2( v, OP_Integer, addrSelect - 1, dest.iParm ); j1 = sqlite3VdbeAddOp2( v, OP_Goto, 0, 0 ); #if SQLITE_DEBUG VdbeComment( v, "Jump over SELECT coroutine" ); #endif /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select( pParse, pSelect, ref dest ); Debug.Assert( pParse.nErr == 0 || rc != 0 ); if ( rc != 0 || NEVER( pParse.nErr != 0 ) /*|| db.mallocFailed != 0 */ ) { goto insert_cleanup; } sqlite3VdbeAddOp2( v, OP_Integer, 1, regEof ); /* EOF <- 1 */ sqlite3VdbeAddOp1( v, OP_Yield, dest.iParm ); /* yield X */ sqlite3VdbeAddOp2( v, OP_Halt, SQLITE_INTERNAL, OE_Abort ); #if SQLITE_DEBUG VdbeComment( v, "End of SELECT coroutine" ); #endif sqlite3VdbeJumpHere( v, j1 ); /* label B: */ regFromSelect = dest.iMem; Debug.Assert( pSelect.pEList != null ); nColumn = pSelect.pEList.nExpr; Debug.Assert( dest.nMem == nColumn ); /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to ** FALSE if each* row of the SELECT can be written directly into ** the destination table (template 3). ** ** A temp table must be used if the table being updated is also one ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ if ( pTrigger != null || readsTable( pParse, addrSelect, iDb, pTab ) ) { useTempTable = true; } if ( useTempTable ) { /* Invoke the coroutine to extract information from the SELECT ** and add it to a transient table srcTab. The code generated ** here is from the 4th template: ** ** B: open temp table ** L: yield X ** if EOF goto M ** insert row from R..R+n into temp table ** goto L ** M: ... */ int regRec; /* Register to hold packed record */ int regTempRowid; /* Register to hold temp table ROWID */ int addrTop; /* Label "L" */ int addrIf; /* Address of jump to M */ srcTab = pParse.nTab++; regRec = sqlite3GetTempReg( pParse ); regTempRowid = sqlite3GetTempReg( pParse ); sqlite3VdbeAddOp2( v, OP_OpenEphemeral, srcTab, nColumn ); addrTop = sqlite3VdbeAddOp1( v, OP_Yield, dest.iParm ); addrIf = sqlite3VdbeAddOp1( v, OP_If, regEof ); sqlite3VdbeAddOp3( v, OP_MakeRecord, regFromSelect, nColumn, regRec ); sqlite3VdbeAddOp2( v, OP_NewRowid, srcTab, regTempRowid ); sqlite3VdbeAddOp3( v, OP_Insert, srcTab, regRec, regTempRowid ); sqlite3VdbeAddOp2( v, OP_Goto, 0, addrTop ); sqlite3VdbeJumpHere( v, addrIf ); sqlite3ReleaseTempReg( pParse, regRec ); sqlite3ReleaseTempReg( pParse, regTempRowid ); } } else { /* This is the case if the data for the INSERT is coming from a VALUES ** clause */ NameContext sNC; sNC = new NameContext();// memset( &sNC, 0, sNC ).Length; sNC.pParse = pParse; srcTab = -1; Debug.Assert( !useTempTable ); nColumn = pList != null ? pList.nExpr : 0; for ( i = 0; i < nColumn; i++ ) { if ( sqlite3ResolveExprNames( sNC, ref pList.a[i].pExpr ) != 0 ) { goto insert_cleanup; } } } /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. */ if ( IsVirtual( pTab ) ) { for ( i = 0; i < pTab.nCol; i++ ) { nHidden += ( IsHiddenColumn( pTab.aCol[i] ) ? 1 : 0 ); } } if ( pColumn == null && nColumn != 0 && nColumn != ( pTab.nCol - nHidden ) ) { sqlite3ErrorMsg( pParse, "table %S has %d columns but %d values were supplied", pTabList, 0, pTab.nCol - nHidden, nColumn ); goto insert_cleanup; } if ( pColumn != null && nColumn != pColumn.nId ) { sqlite3ErrorMsg( pParse, "%d values for %d columns", nColumn, pColumn.nId ); goto insert_cleanup; } /* If the INSERT statement included an IDLIST term, then make sure ** all elements of the IDLIST really are columns of the table and ** remember the column indices. ** ** If the table has an INTEGER PRIMARY KEY column and that column ** is named in the IDLIST, then record in the keyColumn variable ** the index into IDLIST of the primary key column. keyColumn is ** the index of the primary key as it appears in IDLIST, not as ** is appears in the original table. (The index of the primary ** key in the original table is pTab.iPKey.) */ if ( pColumn != null ) { for ( i = 0; i < pColumn.nId; i++ ) { pColumn.a[i].idx = -1; } for ( i = 0; i < pColumn.nId; i++ ) { for ( j = 0; j < pTab.nCol; j++ ) { if ( pColumn.a[i].zName.Equals( pTab.aCol[j].zName ,StringComparison.InvariantCultureIgnoreCase ) ) { pColumn.a[i].idx = j; if ( j == pTab.iPKey ) { keyColumn = i; } break; } } if ( j >= pTab.nCol ) { if ( sqlite3IsRowid( pColumn.a[i].zName ) ) { keyColumn = i; } else { sqlite3ErrorMsg( pParse, "table %S has no column named %s", pTabList, 0, pColumn.a[i].zName ); pParse.checkSchema = 1; goto insert_cleanup; } } } } /* If there is no IDLIST term but the table has an integer primary ** key, the set the keyColumn variable to the primary key column index ** in the original table definition. */ if ( pColumn == null && nColumn > 0 ) { keyColumn = pTab.iPKey; } /* Initialize the count of rows to be inserted */ if ( ( db.flags & SQLITE_CountRows ) != 0 ) { regRowCount = ++pParse.nMem; sqlite3VdbeAddOp2( v, OP_Integer, 0, regRowCount ); } /* If this is not a view, open the table and and all indices */ if ( !isView ) { int nIdx; baseCur = pParse.nTab; nIdx = sqlite3OpenTableAndIndices( pParse, pTab, baseCur, OP_OpenWrite ); aRegIdx = new int[nIdx + 1];// sqlite3DbMallocRaw( db, sizeof( int ) * ( nIdx + 1 ) ); if ( aRegIdx == null ) { goto insert_cleanup; } for ( i = 0; i < nIdx; i++ ) { aRegIdx[i] = ++pParse.nMem; } } /* This is the top of the main insertion loop */ if ( useTempTable ) { /* This block codes the top of loop only. The complete loop is the ** following pseudocode (template 4): ** ** rewind temp table ** C: loop over rows of intermediate table ** transfer values form intermediate table into <table> ** end loop ** D: ... */ addrInsTop = sqlite3VdbeAddOp1( v, OP_Rewind, srcTab ); addrCont = sqlite3VdbeCurrentAddr( v ); } else if ( pSelect != null ) { /* This block codes the top of loop only. The complete loop is the ** following pseudocode (template 3): ** ** C: yield X ** if EOF goto D ** insert the select result into <table> from R..R+n ** goto C ** D: ... */ addrCont = sqlite3VdbeAddOp1( v, OP_Yield, dest.iParm ); addrInsTop = sqlite3VdbeAddOp1( v, OP_If, regEof ); } /* Allocate registers for holding the rowid of the new row, ** the content of the new row, and the assemblied row record. */ regRowid = regIns = pParse.nMem + 1; pParse.nMem += pTab.nCol + 1; if ( IsVirtual( pTab ) ) { regRowid++; pParse.nMem++; } regData = regRowid + 1; /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel( v ); #if !SQLITE_OMIT_TRIGGER if ( ( tmask & TRIGGER_BEFORE ) != 0 ) { int regCols = sqlite3GetTempRange( pParse, pTab.nCol + 1 ); /* build the NEW.* reference row. Note that if there is an INTEGER ** PRIMARY KEY into which a NULL is being inserted, that NULL will be ** translated into a unique ID for the row. But on a BEFORE trigger, ** we do not know what the unique ID will be (because the insert has ** not happened yet) so we substitute a rowid of -1 */ if ( keyColumn < 0 ) { sqlite3VdbeAddOp2( v, OP_Integer, -1, regCols ); } else { int j1; if ( useTempTable ) { sqlite3VdbeAddOp3( v, OP_Column, srcTab, keyColumn, regCols ); } else { Debug.Assert( pSelect == null ); /* Otherwise useTempTable is true */ sqlite3ExprCode( pParse, pList.a[keyColumn].pExpr, regCols ); } j1 = sqlite3VdbeAddOp1( v, OP_NotNull, regCols ); sqlite3VdbeAddOp2( v, OP_Integer, -1, regCols ); sqlite3VdbeJumpHere( v, j1 ); sqlite3VdbeAddOp1( v, OP_MustBeInt, regCols ); } /* Cannot have triggers on a virtual table. If it were possible, ** this block would have to account for hidden column. */ Debug.Assert( !IsVirtual( pTab ) ); /* Create the new column data */ for ( i = 0; i < pTab.nCol; i++ ) { if ( pColumn == null ) { j = i; } else { for ( j = 0; j < pColumn.nId; j++ ) { if ( pColumn.a[j].idx == i ) break; } } if ( ( !useTempTable && null == pList ) || ( pColumn != null && j >= pColumn.nId ) ) { sqlite3ExprCode( pParse, pTab.aCol[i].pDflt, regCols + i + 1 ); } else if ( useTempTable ) { sqlite3VdbeAddOp3( v, OP_Column, srcTab, j, regCols + i + 1 ); } else { Debug.Assert( pSelect == null ); /* Otherwise useTempTable is true */ sqlite3ExprCodeAndCache( pParse, pList.a[j].pExpr, regCols + i + 1 ); } } /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, ** do not attempt any conversions before assembling the record. ** If this is a real table, attempt conversions as required by the ** table column affinities. */ if ( !isView ) { sqlite3VdbeAddOp2( v, OP_Affinity, regCols + 1, pTab.nCol ); sqlite3TableAffinityStr( v, pTab ); } /* Fire BEFORE or INSTEAD OF triggers */ sqlite3CodeRowTrigger( pParse, pTrigger, TK_INSERT, null, TRIGGER_BEFORE, pTab, regCols - pTab.nCol - 1, onError, endOfLoop ); sqlite3ReleaseTempRange( pParse, regCols, pTab.nCol + 1 ); } #endif /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRowid ** except when the table has an INTEGER PRIMARY KEY column, in which ** case the record number is the same as that column. */ if ( !isView ) { if ( IsVirtual( pTab ) ) { /* The row that the VUpdate opcode will delete: none */ sqlite3VdbeAddOp2( v, OP_Null, 0, regIns ); } if ( keyColumn >= 0 ) { if ( useTempTable ) { sqlite3VdbeAddOp3( v, OP_Column, srcTab, keyColumn, regRowid ); } else if ( pSelect != null ) { sqlite3VdbeAddOp2( v, OP_SCopy, regFromSelect + keyColumn, regRowid ); } else { VdbeOp pOp; sqlite3ExprCode( pParse, pList.a[keyColumn].pExpr, regRowid ); pOp = sqlite3VdbeGetOp( v, -1 ); if ( ALWAYS( pOp != null ) && pOp.opcode == OP_Null && !IsVirtual( pTab ) ) { appendFlag = true; pOp.opcode = OP_NewRowid; pOp.p1 = baseCur; pOp.p2 = regRowid; pOp.p3 = regAutoinc; } } /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid ** to generate a unique primary key value. */ if ( !appendFlag ) { int j1; if ( !IsVirtual( pTab ) ) { j1 = sqlite3VdbeAddOp1( v, OP_NotNull, regRowid ); sqlite3VdbeAddOp3( v, OP_NewRowid, baseCur, regRowid, regAutoinc ); sqlite3VdbeJumpHere( v, j1 ); } else { j1 = sqlite3VdbeCurrentAddr( v ); sqlite3VdbeAddOp2( v, OP_IsNull, regRowid, j1 + 2 ); } sqlite3VdbeAddOp1( v, OP_MustBeInt, regRowid ); } } else if ( IsVirtual( pTab ) ) { sqlite3VdbeAddOp2( v, OP_Null, 0, regRowid ); } else { sqlite3VdbeAddOp3( v, OP_NewRowid, baseCur, regRowid, regAutoinc ); appendFlag = true; } autoIncStep( pParse, regAutoinc, regRowid ); /* Push onto the stack, data for all columns of the new entry, beginning ** with the first column. */ nHidden = 0; for ( i = 0; i < pTab.nCol; i++ ) { int iRegStore = regRowid + 1 + i; if ( i == pTab.iPKey ) { /* The value of the INTEGER PRIMARY KEY column is always a NULL. ** Whenever this column is read, the record number will be substituted ** in its place. So will fill this column with a NULL to avoid ** taking up data space with information that will never be used. */ sqlite3VdbeAddOp2( v, OP_Null, 0, iRegStore ); continue; } if ( pColumn == null ) { if ( IsHiddenColumn( pTab.aCol[i] ) ) { Debug.Assert( IsVirtual( pTab ) ); j = -1; nHidden++; } else { j = i - nHidden; } } else { for ( j = 0; j < pColumn.nId; j++ ) { if ( pColumn.a[j].idx == i ) break; } } if ( j < 0 || nColumn == 0 || ( pColumn != null && j >= pColumn.nId ) ) { sqlite3ExprCode( pParse, pTab.aCol[i].pDflt, iRegStore ); } else if ( useTempTable ) { sqlite3VdbeAddOp3( v, OP_Column, srcTab, j, iRegStore ); } else if ( pSelect != null ) { sqlite3VdbeAddOp2( v, OP_SCopy, regFromSelect + j, iRegStore ); } else { sqlite3ExprCode( pParse, pList.a[j].pExpr, iRegStore ); } } /* Generate code to check constraints and generate index keys and ** do the insertion. */ #if !SQLITE_OMIT_VIRTUALTABLE if ( IsVirtual( pTab ) ) { VTable pVTab = sqlite3GetVTable( db, pTab ); sqlite3VtabMakeWritable( pParse, pTab ); sqlite3VdbeAddOp4( v, OP_VUpdate, 1, pTab.nCol + 2, regIns, pVTab, P4_VTAB ); sqlite3VdbeChangeP5( v, (byte)( onError == OE_Default ? OE_Abort : onError ) ); sqlite3MayAbort( pParse ); } else #endif { int isReplace = 0; /* Set to true if constraints may cause a replace */ sqlite3GenerateConstraintChecks( pParse, pTab, baseCur, regIns, aRegIdx, keyColumn >= 0 ? 1 : 0, false, onError, endOfLoop, out isReplace ); sqlite3FkCheck( pParse, pTab, 0, regIns ); sqlite3CompleteInsertion( pParse, pTab, baseCur, regIns, aRegIdx, false, appendFlag, isReplace == 0 ); } } /* Update the count of rows that are inserted */ if ( ( db.flags & SQLITE_CountRows ) != 0 ) { sqlite3VdbeAddOp2( v, OP_AddImm, regRowCount, 1 ); } #if !SQLITE_OMIT_TRIGGER if ( pTrigger != null ) { /* Code AFTER triggers */ sqlite3CodeRowTrigger( pParse, pTrigger, TK_INSERT, null, TRIGGER_AFTER, pTab, regData - 2 - pTab.nCol, onError, endOfLoop ); } #endif /* The bottom of the main insertion loop, if the data source ** is a SELECT statement. */ sqlite3VdbeResolveLabel( v, endOfLoop ); if ( useTempTable ) { sqlite3VdbeAddOp2( v, OP_Next, srcTab, addrCont ); sqlite3VdbeJumpHere( v, addrInsTop ); sqlite3VdbeAddOp1( v, OP_Close, srcTab ); } else if ( pSelect != null ) { sqlite3VdbeAddOp2( v, OP_Goto, 0, addrCont ); sqlite3VdbeJumpHere( v, addrInsTop ); } if ( !IsVirtual( pTab ) && !isView ) { /* Close all tables opened */ sqlite3VdbeAddOp1( v, OP_Close, baseCur ); for ( idx = 1, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, idx++ ) { sqlite3VdbeAddOp1( v, OP_Close, idx + baseCur ); } } insert_end: /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if ( pParse.nested == 0 && pParse.pTriggerTab == null ) { sqlite3AutoincrementEnd( pParse ); } /* ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if ( ( db.flags & SQLITE_CountRows ) != 0 && 0 == pParse.nested && null == pParse.pTriggerTab ) { sqlite3VdbeAddOp2( v, OP_ResultRow, regRowCount, 1 ); sqlite3VdbeSetNumCols( v, 1 ); sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC ); } insert_cleanup: sqlite3SrcListDelete( db, ref pTabList ); sqlite3ExprListDelete( db, ref pList ); sqlite3SelectDelete( db, ref pSelect ); sqlite3IdListDelete( db, ref pColumn ); sqlite3DbFree( db, ref aRegIdx ); }
static void sqlite3Insert( Parse pParse, SrcList pTabList, int null_3, Select pSelect, IdList pColumn, int onError ) { sqlite3Insert( pParse, pTabList, null, pSelect, pColumn, onError ); }
void IdentifierList(out IdList list) { list = new IdList(); string name; Identifier(out name); list.Add(name); while (la.kind == 14) { Get(); Identifier(out name); list.Add(name); } }
// OVERLOADS, so I don't need to rewrite parse.c public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, int null_4, int null_5, OE orconf) { return(TriggerInsertStep(ctx, tableName, column, null, null, orconf)); }
/* ** Build a trigger step out of an INSERT statement. Return a pointer ** to the new trigger step. ** ** The parser calls this routine when it sees an INSERT inside the ** body of a trigger. */ // OVERLOADS, so I don't need to rewrite parse.c private static TriggerStep sqlite3TriggerInsertStep(sqlite3 db, Token pTableName, IdList pColumn, int null_4, int null_5, u8 orconf) { return sqlite3TriggerInsertStep(db, pTableName, pColumn, null, null, orconf); }
void StateIdentifierList(out IdList list) { list = null; if (la.kind == 1) { IdentifierList(out list); } else if (la.kind == 31) { Get(); list = new IdList(true); } else if (la.kind == 32) { Get(); list = new IdList("0"); } else if (la.kind == 33) { Get(); list = new IdList("1"); } else SynErr(43); }
public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, ExprList list, int null_5, OE orconf) { return TriggerInsertStep(ctx, tableName, column, list, null, orconf); }
static void sqlite3Insert( Parse pParse, SrcList pTabList, ExprList pList, int null_4, IdList pColumn, int onError ) { sqlite3Insert( pParse, pTabList, pList, null, pColumn, onError ); }
public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, int null_4, Select select, OE orconf) { return TriggerInsertStep(ctx, tableName, column, null, select, orconf); }
static IdList sqlite3IdListDup( sqlite3 db, IdList p ) { IdList pNew; int i; if ( p == null ) return null; pNew = new IdList();//sqlite3DbMallocRaw(db, sizeof(*pNew) ); if ( pNew == null ) return null; pNew.nId = pNew.nAlloc = p.nId; pNew.a = new IdList_item[p.nId];//sqlite3DbMallocRaw(db, p.nId*sizeof(p.a[0]) ); if ( pNew.a == null ) { sqlite3DbFree( db, ref pNew ); return null; } for ( i = 0; i < p.nId; i++ ) { pNew.a[i] = new IdList_item(); IdList_item pNewItem = pNew.a[i]; IdList_item pOldItem = p.a[i]; pNewItem.zName = pOldItem.zName;// sqlite3DbStrDup(db, pOldItem.zName); pNewItem.idx = pOldItem.idx; } return pNew; }
public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, ExprList list, Select select, OE orconf) { Debug.Assert(list == null || select == null); Debug.Assert(list != null || select != null || ctx.MallocFailed); TriggerStep triggerStep = TriggerStepAllocate(ctx, TK.INSERT, tableName); if (triggerStep != null) { triggerStep.Select = Select.Dup(ctx, select, E.EXPRDUP_REDUCE); triggerStep.IdList = column; triggerStep.ExprList = Expr.ListDup(ctx, list, E.EXPRDUP_REDUCE); triggerStep.Orconf = orconf; } else Expr.IdListDelete(ctx, ref column); Expr.ListDelete(ctx, ref list); Select.Delete(ctx, ref select); return triggerStep; }
static string Example4() { StmtList sl1 = new StmtList(); Sub foo = new Sub("foo", sl1); Pirate p = new Pirate(); p.Add(foo); ParamDecl pd1 = new ParamDecl(); pd1.type = new IntType(); IdList idl1 = new IdList(); NamedReg n = new NamedReg(); n.name = "n"; idl1.Add(n); pd1.id_list = idl1; sl1.Add(pd1); ParamDecl pd2 = new ParamDecl(); pd2.type = new StringType(); IdList idl2 = new IdList(); NamedReg message = new NamedReg(); message.name = "message"; idl2.Add(message); pd2.id_list = idl2; sl1.Add(pd2); StringWriter sw = new StringWriter(); PirateWriter pv = new PirateWriter(sw); DynamicVisitor.accept(p, pv); return sw.ToString(); }
static bool CheckColumnOverlap(IdList idList, ExprList eList) { if (idList == null || C._NEVER(eList == null)) return true; for (int e = 0; e < eList.Exprs; e++) if (Expr.IdListIndex(idList, eList.Ids[e].Name) >= 0) return true; return false; }
static string Example2() { NamedReg a = new NamedReg("a"); NamedReg b = new NamedReg("b"); NamedReg c = new NamedReg("c"); NamedReg det = new NamedReg("det"); IdList rl1 = new IdList(); rl1.Add(a); rl1.Add(b); rl1.Add(c); rl1.Add(det); LocalDecl ld1 = new LocalDecl(new NumType(), rl1); IntLiteral il3 = new IntLiteral(2); Assign a12 = new Assign(a, il3); IntLiteral il4 = new IntLiteral(-3); Assign a13 = new Assign(b, il4); IntLiteral il5 = new IntLiteral(-2); Assign a14 = new Assign(c, il5); UnaryNeg un1 = new UnaryNeg(b); TmpNumReg tnr0 = new TmpNumReg(0); Assign a1 = new Assign(tnr0, un1); TmpNumReg tnr1 = new TmpNumReg(1); BinaryMul bm1 = new BinaryMul(b, b); Assign a2 = new Assign(tnr1, bm1); TmpNumReg tnr2 = new TmpNumReg(2); IntLiteral il1 = new IntLiteral(4); BinaryMul bm2 = new BinaryMul(il1, a); Assign a3 = new Assign(tnr2, bm2); BinaryMul bm3 = new BinaryMul(tnr2, c); Assign a4 = new Assign(tnr2, bm3); TmpNumReg tnr3 = new TmpNumReg(3); IntLiteral il2 = new IntLiteral(2); BinaryMul bm4 = new BinaryMul(il2, a); Assign a5 = new Assign(tnr3, bm4); BinarySub bs1 = new BinarySub(tnr1, tnr2); Assign a6 = new Assign(det, bs1); TmpNumReg tnr4 = new TmpNumReg(4); Call sqrt = new Call("sqrt", det); Assign a7 = new Assign(tnr4, sqrt); NamedReg x1 = new NamedReg("x1"); NamedReg x2 = new NamedReg("x2"); IdList rl2 = new IdList(); rl2.Add(x1); rl2.Add(x2); LocalDecl ld2 = new LocalDecl(new NumType(), rl2); BinaryAdd ba1 = new BinaryAdd(tnr0, tnr4); Assign a8 = new Assign(x1, ba1); BinaryDiv bd1 = new BinaryDiv(x1, tnr3); Assign a9 = new Assign(x1, bd1); BinarySub bs2 = new BinarySub(tnr0, tnr4); Assign a10 = new Assign(x2, bs2); AssignDiv a11 = new AssignDiv(x2, tnr3); StringLiteral s1 = new StringLiteral("Answers to ABC formula are:\n"); Call c1 = new Call("print", s1); CallStmt print1 = new CallStmt(c1); StringLiteral s2 = new StringLiteral("x1 = "); Call c2 = new Call("print", s2); CallStmt print2 = new CallStmt(c2); Call c3 = new Call("print", x1); CallStmt print3 = new CallStmt(c3); StringLiteral s4 = new StringLiteral("\nx2 = "); Call c4 = new Call("print", s4); CallStmt print4 = new CallStmt(c4); Call c5 = new Call("print", x2); CallStmt print5 = new CallStmt(c5); StringLiteral s6 = new StringLiteral("\n"); Call c6 = new Call("print", s6); CallStmt print6 = new CallStmt(c6); StmtList sl1 = new StmtList(); sl1.Add(ld1); sl1.Add(a12); sl1.Add(a13); sl1.Add(a14); sl1.Add(a1); sl1.Add(a2); sl1.Add(a3); sl1.Add(a4); sl1.Add(a5); sl1.Add(a6); sl1.Add(a7); sl1.Add(ld2); sl1.Add(a8); sl1.Add(a9); sl1.Add(a10); sl1.Add(a11); sl1.Add(print1); sl1.Add(print2); sl1.Add(print3); sl1.Add(print4); sl1.Add(print5); sl1.Add(print6); Sub foo = new Sub("foo", sl1); Pirate p = new Pirate(); p.Add(foo); StringWriter sw = new StringWriter(); PirateWriter pv = new PirateWriter(sw); DynamicVisitor.accept(p, pv); return sw.ToString(); }
public static void BeginTrigger(Parse parse, Token name1, Token name2, TK trTm, TK op, IdList columns, SrcList tableName, Expr when, bool isTemp, int noErr) { Context ctx = parse.Ctx; // The database connection Debug.Assert(name1 != null); // pName1.z might be NULL, but not pName1 itself Debug.Assert(name2 != null); Debug.Assert(op == TK.INSERT || op == TK.UPDATE || op == TK.DELETE); Debug.Assert(op > 0 && op < (TK)0xff); Trigger trigger = null; // The new trigger int db; // The database to store the trigger in Token name = null; // The unqualified db name if (isTemp) { // If TEMP was specified, then the trigger name may not be qualified. if (name2.length > 0) { parse.ErrorMsg("temporary trigger may not have qualified name"); goto trigger_cleanup; } db = 1; name = name1; } else { // Figure out the db that the the trigger will be created in db = parse.TwoPartName(name1, name2, ref name); if (db < 0) goto trigger_cleanup; } if (tableName == null || ctx.MallocFailed) goto trigger_cleanup; // A long-standing parser bug is that this syntax was allowed: // CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab .... // ^^^^^^^^ // To maintain backwards compatibility, ignore the database name on pTableName if we are reparsing our of SQLITE_MASTER. if (ctx.Init.Busy && db != 1) { C._tagfree(ctx, ref tableName.Ids[0].Database); tableName.Ids[0].Database = null; } // If the trigger name was unqualified, and the table is a temp table, then set iDb to 1 to create the trigger in the temporary database. // If sqlite3SrcListLookup() returns 0, indicating the table does not exist, the error is caught by the block below. //? if (tableName == null) goto trigger_cleanup; Table table = Delete.SrcListLookup(parse, tableName); // Table that the trigger fires off of if (ctx.Init.Busy == null && name2.length == 0 && table != null && table.Schema == ctx.DBs[1].Schema) db = 1; // Ensure the table name matches database name and that the table exists if (ctx.MallocFailed) goto trigger_cleanup; Debug.Assert(tableName.Srcs == 1); DbFixer sFix = new DbFixer(); // State vector for the DB fixer if (sFix.FixInit(parse, db, "trigger", name) && sFix.FixSrcList(tableName)) goto trigger_cleanup; table = Delete.SrcListLookup(parse, tableName); if (table == null) { // The table does not exist. if (ctx.Init.DB == 1) { // Ticket #3810. // Normally, whenever a table is dropped, all associated triggers are dropped too. But if a TEMP trigger is created on a non-TEMP table // and the table is dropped by a different database connection, the trigger is not visible to the database connection that does the // drop so the trigger cannot be dropped. This results in an "orphaned trigger" - a trigger whose associated table is missing. ctx.Init.OrphanTrigger = true; } goto trigger_cleanup; } if (E.IsVirtual(table)) { parse.ErrorMsg("cannot create triggers on virtual tables"); goto trigger_cleanup; } // Check that the trigger name is not reserved and that no trigger of the specified name exists string nameAsString = Parse.NameFromToken(ctx, name); if (nameAsString == null || parse.CheckObjectName(nameAsString) != RC.OK) goto trigger_cleanup; Debug.Assert(Btree.SchemaMutexHeld(ctx, db, null)); if (ctx.DBs[db].Schema.TriggerHash.Find(nameAsString, nameAsString.Length, (Trigger)null) != null) { if (noErr == 0) parse.ErrorMsg("trigger %T already exists", name); else { Debug.Assert(!ctx.Init.Busy); parse.CodeVerifySchema(db); } goto trigger_cleanup; } // Do not create a trigger on a system table if (table.Name.StartsWith("sqlite_", StringComparison.InvariantCultureIgnoreCase)) { parse.ErrorMsg("cannot create trigger on system table"); parse.Errs++; goto trigger_cleanup; } // INSTEAD of triggers are only for views and views only support INSTEAD of triggers. if (table.Select != null && trTm != TK.INSTEAD) { parse.ErrorMsg("cannot create %s trigger on view: %S", (trTm == TK.BEFORE ? "BEFORE" : "AFTER"), tableName, 0); goto trigger_cleanup; } if (table.Select == null && trTm == TK.INSTEAD) { parse.ErrorMsg("cannot create INSTEAD OF trigger on table: %S", tableName, 0); goto trigger_cleanup; } #if !OMIT_AUTHORIZATION { int tabDb = Prepare.SchemaToIndex(ctx, table.Schema); // Index of the database holding pTab AUTH code = AUTH.CREATE_TRIGGER; string dbName = ctx.DBs[tabDb].Name; string dbTrigName = (isTemp ? ctx.DBs[1].Name : dbName); if (tabDb == 1 || isTemp) code = AUTH.CREATE_TEMP_TRIGGER; if (Auth.Check(parse, code, nameAsString, table.Name, dbTrigName) != 0 || Auth.Check(parse, AUTH.INSERT, E.SCHEMA_TABLE(tabDb), 0, dbName)) goto trigger_cleanup; } #endif // INSTEAD OF triggers can only appear on views and BEFORE triggers cannot appear on views. So we might as well translate every // INSTEAD OF trigger into a BEFORE trigger. It simplifies code elsewhere. if (trTm == TK.INSTEAD) trTm = TK.BEFORE; // Build the Trigger object trigger = new Trigger(); //: (Trigger *)_tagalloc(db, sizeof(Trigger), true); if (trigger == null) goto trigger_cleanup; trigger.Name = name; trigger.Table = tableName.Ids[0].Name; //: _tagstrdup(ctx, tableName->Ids[0].Name); trigger.Schema = ctx.DBs[db].Schema; trigger.TabSchema = table.Schema; trigger.OP = op; trigger.TRtm = (trTm == TK.BEFORE ? TRIGGER.BEFORE : TRIGGER.AFTER); trigger.When = Expr.Dup(db, when, E.EXPRDUP_REDUCE); trigger.Columns = Expr.IdListDup(ctx, columns); Debug.Assert(parse.NewTrigger == null); parse.NewTrigger = trigger; trigger_cleanup: C._tagfree(ctx, ref name); Expr.SrcListDelete(ctx, ref tableName); Expr.IdListDelete(ctx, ref columns); Expr.Delete(ctx, ref when); if (parse.NewTrigger == null) DeleteTrigger(ctx, ref trigger); else Debug.Assert(parse.NewTrigger == trigger); }
static TriggerStep sqlite3TriggerInsertStep( sqlite3 db, Token pTableName, IdList pColumn, ExprList pEList, int null_5, u8 orconf ) { return sqlite3TriggerInsertStep( db, pTableName, pColumn, pEList, null, orconf ); }
/// <summary> /// Sets the PRE states of a state transition condition. /// </summary> /// <param name="names"></param> public void SetPreStates(IdList names) { StateIndexes.AddRange(Variable.Type.GetIndexesOfNames(names)); PreWildcard = names.Wildcard; }
static TriggerStep sqlite3TriggerInsertStep( sqlite3 db, /* The database connection */ Token pTableName, /* Name of the table into which we insert */ IdList pColumn, /* List of columns in pTableName to insert into */ ExprList pEList, /* The VALUE clause: a list of values to be inserted */ Select pSelect, /* A SELECT statement that supplies values */ u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ) { TriggerStep pTriggerStep; Debug.Assert( pEList == null || pSelect == null ); Debug.Assert( pEList != null || pSelect != null /*|| db.mallocFailed != 0 */ ); pTriggerStep = triggerStepAllocate( db, TK_INSERT, pTableName ); //if ( pTriggerStep != null ) //{ pTriggerStep.pSelect = sqlite3SelectDup( db, pSelect, EXPRDUP_REDUCE ); pTriggerStep.pIdList = pColumn; pTriggerStep.pExprList = sqlite3ExprListDup( db, pEList, EXPRDUP_REDUCE ); pTriggerStep.orconf = orconf; //} //else //{ // sqlite3IdListDelete( db, ref pColumn ); //} sqlite3ExprListDelete( db, ref pEList ); sqlite3SelectDelete( db, ref pSelect ); return pTriggerStep; }
//----------------------------------------------------------- //<var-list>// <-- //<id-list>// //<paramList>// <-- //<id-List> public void Visit(IdList node, int i) { VisitChildren(node, i); }