问:
How to add properties at runtime to JSON (C#)
Note: Im working with  System.Text.Json package
Below is JSON I am getting from a database. I have to go through each of the keys in the JSON and check if there is a period (.) in the key name; if so, I need to add a property required with the value of true in the JSON in order to provide runtime validation:

```<code>validate:{"required", true}
</code>```

Here is my JSON:

```<code>{
    "display": "wizard",
    "settings": {},
    "components": [{
        "title": "Event Information",
        "label": "Event Information",
        "type": "panel",
        "key": "EventInformation",
        "components": [{
            "label": "Row1Columns",
            "columns": [{
                "components": [{
                    "label": "Event Date",
                    "format": "dd/MM/yyyy hh:mm a",
                    "tableView": false,
                    "datePicker": {
                        "disableWeekends": false,
                        "disableWeekdays": false
                    },
                    "validate": {
                        "unique": true
                    },
                    "key": "Event.EventDate",
                    "type": "datetime",
                    "input": true,
                    "suffix": "<i ref=\"icon\" class=\"fa fa-calendar\" style=\"\"></i>",
                    "widget": {
                        "type": "calendar",
                        "displayInTimezone": "viewer",
                        "language": "en",
                        "useLocaleSettings": false,
                        "allowInput": true,
                        "mode": "single",
                        "enableTime": true,
                        "noCalendar": false,
                        "format": "dd/MM/yyyy hh:mm a",
                        "hourIncrement": 1,
                        "minuteIncrement": 1,
                        "time_24hr": false,
                        "minDate": null,
                        "disableWeekends": false,
                        "disableWeekdays": false,
                        "maxDate": null
                    }
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }, {
                "components": [{
                    "label": "Duration (minutes)",
                    "mask": false,
                    "spellcheck": true,
                    "tableView": false,
                    "delimiter": false,
                    "requireDecimal": false,
                    "inputFormat": "plain",
                    "key": "Event.Duration",
                    "type": "number",
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }],
            "tableView": false,
            "key": "row1Columns",
            "type": "columns",
            "input": false
        }, {
            "label": "Row2Columns",
            "columns": [{
                "components": [{
                    "label": "Event Category",
                    "widget": "choicesjs",
                    "tableView": true,
                    "dataSrc": "custom",
                    "data": {
                        "custom": "values = getEventCategoryValues()"
                    },
                    "valueProperty": "AgencyEventCategoryId",
                    "template": "<span>{{ item.text }}</span>",
                    "selectThreshold": 0.3,
                    "validate": {
                        "required": true
                    },
                    "key": "Event.AgencyEventCategoryId",
                    "type": "select",
                    "indexeddb": {
                        "filter": {}
                    },
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }, {
                "components": [{
                    "label": "Attendance",
                    "widget": "choicesjs",
                    "tableView": true,
                    "multiple": false,
                    "dataSrc": "custom",
                    "data": {
                        "custom": "values = getAttendanceValues()"
                    },
                    "valueProperty": "AgencyEventAttendanceId",
                    "template": "<span>{{ item.text }}</span>",
                    "selectThreshold": 0.3,
                    "validate": {
                        "required": true,
                    },
                    "key": "Event.AgencyEventAttendanceId",
                    "type": "select",
                    "indexeddb": {
                        "filter": {}
                    },
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }],
            "tableView": false,
            "key": "row2Columns",
            "type": "columns",
            "input": false
        }, {
            "label": "Event Options",
            "widget": "choicesjs",
            "tableView": true,
            "multiple": true,
            "dataSrc": "custom",
            "data": {
                "custom": "values = getEventManagerValues(data.Event.AgencyEventCategoryId)"
            },
            "template": "<span>{{ item.text }}</span>",
            "refreshOn": "Event.AgencyEventCategoryId",
            "clearOnRefresh": true,
            "selectThreshold": 0.3,
            "calculateServer": false,
            "validate": {
                "required": true,
                "multiple": true
            },
            "key": "Event.EventDetail",
            "type": "select",
            "indexeddb": {
                "filter": {}
            },
            "input": true
        }, {
            "label": "Casenote",
            "wysiwyg": true,
            "autoExpand": true,
            "spellcheck": true,
            "tableView": true,
            "calculateServer": false,
            "key": "Event.EventCasenote[0].Casenote",
            "type": "textarea",
            "input": true
        }],
        "input": false,
        "tableView": false,
        "breadcrumbClickable": true,
        "buttonSettings": {
            "previous": true,
            "cancel": true,
            "next": true
        },
        "collapsible": false
    }]
}
</code>```

答:
One of the options would be to parse json into JObject and add property to it via Newtonsoft's Json.NET:

```<code>var obj = JObject.Parse("{'key':'value'}");
obj.Add("required", true);
Console.WriteLine(obj); // { "key": "value", "required": true }
</code>```

To add new object you can use this overload of Add:

```<code>obj.Add("validate", JObject.FromObject(new { required = true }));
</code>```

So the whole solution will look something like this:

```<code>var obj = JObect.Parse(your_json);

foreach(var token in obj.DescendantsAndSelf().ToList()) // ToList is important!!!
{
    if(token is JObject xObj)
    {
        // check your conditions for adding property
        // check if object does not have "validate" property
        if(satisfies_all_conditions)
        {
            xObj.Add("validate", JObject.FromObject(new { required = true }));
        }
    }
}
</code>```

Body:
Note: Im working with  System.Text.Json package
Below is JSON I am getting from a database. I have to go through each of the keys in the JSON and check if there is a period (.) in the key name; if so, I need to add a property required with the value of true in the JSON in order to provide runtime validation:

validate:{"required", true}

Here is my JSON:

{
    "display": "wizard",
    "settings": {},
    "components": [{
        "title": "Event Information",
        "label": "Event Information",
        "type": "panel",
        "key": "EventInformation",
        "components": [{
            "label": "Row1Columns",
            "columns": [{
                "components": [{
                    "label": "Event Date",
                    "format": "dd/MM/yyyy hh:mm a",
                    "tableView": false,
                    "datePicker": {
                        "disableWeekends": false,
                        "disableWeekdays": false
                    },
                    "validate": {
                        "unique": true
                    },
                    "key": "Event.EventDate",
                    "type": "datetime",
                    "input": true,
                    "suffix": "",
                    "widget": {
                        "type": "calendar",
                        "displayInTimezone": "viewer",
                        "language": "en",
                        "useLocaleSettings": false,
                        "allowInput": true,
                        "mode": "single",
                        "enableTime": true,
                        "noCalendar": false,
                        "format": "dd/MM/yyyy hh:mm a",
                        "hourIncrement": 1,
                        "minuteIncrement": 1,
                        "time_24hr": false,
                        "minDate": null,
                        "disableWeekends": false,
                        "disableWeekdays": false,
                        "maxDate": null
                    }
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }, {
                "components": [{
                    "label": "Duration (minutes)",
                    "mask": false,
                    "spellcheck": true,
                    "tableView": false,
                    "delimiter": false,
                    "requireDecimal": false,
                    "inputFormat": "plain",
                    "key": "Event.Duration",
                    "type": "number",
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }],
            "tableView": false,
            "key": "row1Columns",
            "type": "columns",
            "input": false
        }, {
            "label": "Row2Columns",
            "columns": [{
                "components": [{
                    "label": "Event Category",
                    "widget": "choicesjs",
                    "tableView": true,
                    "dataSrc": "custom",
                    "data": {
                        "custom": "values = getEventCategoryValues()"
                    },
                    "valueProperty": "AgencyEventCategoryId",
                    "template": "{{ item.text }}",
                    "selectThreshold": 0.3,
                    "validate": {
                        "required": true
                    },
                    "key": "Event.AgencyEventCategoryId",
                    "type": "select",
                    "indexeddb": {
                        "filter": {}
                    },
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }, {
                "components": [{
                    "label": "Attendance",
                    "widget": "choicesjs",
                    "tableView": true,
                    "multiple": false,
                    "dataSrc": "custom",
                    "data": {
                        "custom": "values = getAttendanceValues()"
                    },
                    "valueProperty": "AgencyEventAttendanceId",
                    "template": "{{ item.text }}",
                    "selectThreshold": 0.3,
                    "validate": {
                        "required": true,
                    },
                    "key": "Event.AgencyEventAttendanceId",
                    "type": "select",
                    "indexeddb": {
                        "filter": {}
                    },
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }],
            "tableView": false,
            "key": "row2Columns",
            "type": "columns",
            "input": false
        }, {
            "label": "Event Options",
            "widget": "choicesjs",
            "tableView": true,
            "multiple": true,
            "dataSrc": "custom",
            "data": {
                "custom": "values = getEventManagerValues(data.Event.AgencyEventCategoryId)"
            },
            "template": "{{ item.text }}",
            "refreshOn": "Event.AgencyEventCategoryId",
            "clearOnRefresh": true,
            "selectThreshold": 0.3,
            "calculateServer": false,
            "validate": {
                "required": true,
                "multiple": true
            },
            "key": "Event.EventDetail",
            "type": "select",
            "indexeddb": {
                "filter": {}
            },
            "input": true
        }, {
            "label": "Casenote",
            "wysiwyg": true,
            "autoExpand": true,
            "spellcheck": true,
            "tableView": true,
            "calculateServer": false,
            "key": "Event.EventCasenote[0].Casenote",
            "type": "textarea",
            "input": true
        }],
        "input": false,
        "tableView": false,
        "breadcrumbClickable": true,
        "buttonSettings": {
            "previous": true,
            "cancel": true,
            "next": true
        },
        "collapsible": false
    }]
}

Body:
One of the options would be to parse json into JObject and add property to it via Newtonsoft's Json.NET:

var obj = JObject.Parse("{'key':'value'}");
obj.Add("required", true);
Console.WriteLine(obj); // { "key": "value", "required": true }

To add new object you can use this overload of Add:

obj.Add("validate", JObject.FromObject(new { required = true }));

So the whole solution will look something like this:

var obj = JObect.Parse(your_json);

foreach(var token in obj.DescendantsAndSelf().ToList()) // ToList is important!!!
{
    if(token is JObject xObj)
    {
        // check your conditions for adding property
        // check if object does not have "validate" property
        if(satisfies_all_conditions)
        {
            xObj.Add("validate", JObject.FromObject(new { required = true }));
        }
    }
}


来源: stackexchange

问:
Is it safe to apply Terraform plan when it says the database instance must be replaced?
I'm importing the existing resources (AWS RDS) but the terraform plan command showed a summary:

```<code>#aws_db_instance.my_main_db must be replaced
+/- resource "aws_db_instance" "my_main_db" {
~ address = x
allocated_storage = x
+ apply_immediately = x
~ arn = x
~ username = x
+ password = x
(others arguments with alot of +/- and ~)
}
</code>```

my_main_db is online with persistent data. My question is as the title; Is it safe for the existing database to run terrafrom apply? I don't want to lose all my customer data.

答: It's most likely not safe, but really only someone familiar with the application can make that decision. Look at the properties and what is going to change or be recreated. Unless you are comfortable with all of those properties changing, then it's not safe. </p>

ContentLicense: CC BY-SA 4.0

Body:
I'm importing the existing resources (AWS RDS) but the terraform plan command showed a summary:

#aws_db_instance.my_main_db must be replaced
+/- resource "aws_db_instance" "my_main_db" {
~ address = x
allocated_storage = x
+ apply_immediately = x
~ arn = x
~ username = x
+ password = x
(others arguments with alot of +/- and ~)
}

my_main_db is online with persistent data. My question is as the title; Is it safe for the existing database to run terrafrom apply? I don't want to lose all my customer data.


问:
Django Development: Chrome warns "Change Password"
im new at django and for learning i create a fantasy project. By testing my website i was been warned from my Chrome browser that i should change my password. The exact message is

Due to a data breach on a website or in an app your password was disclosed. Chrome recommends changing your password to 127.0.0.1:8000.

is there anything in my code that makes this data breach?

Thanks for helping!

forms.py

```<code>class RegisterForm(forms.Form):

username = forms.CharField(
    label='Benutzername',
    max_length=150,
    required=True,
    widget=forms.TextInput(
        attrs={
            'placeholder': 'Username',
        }
    )
)

email = forms.EmailField(
    label='E-Mail Adresse',
    max_length=254,
    required=True,
    widget=forms.EmailInput(
        attrs={
            'placeholder': 'email@exapmle.com',
        }
    )
)

password = forms.CharField(
    label='Passwort',
    max_length=254,
    required=True,
    widget=forms.PasswordInput(
        attrs={
            'placeholder': 'Password',
        }
    )
)

repeatPassword = forms.CharField(
    label='Passwort wiederholen',
    max_length=254, required=True,
    widget=forms.PasswordInput(
        attrs={
            'placeholder': 'Password',
        }
    )
)

name = forms.CharField(
    label='Nachname',
    max_length=150,
    required=False,
    widget=forms.TextInput(
        attrs={
            'placeholder': 'Last Name',
        }
    )
)

firstName = forms.CharField(
    label='Vorname',
    max_length=150,
    required=False,
    widget=forms.TextInput(
        attrs={
            'placeholder': 'First name',
        }
    )
)

def clean(self):
    cleaned_data = super(RegisterForm, self).clean()
    username = cleaned_data.get('username')
    email = cleaned_data.get('email')
    password = cleaned_data.get('password')
    repeatPassword = cleaned_data.get('repeatPassword')
    name = cleaned_data.get('name')
    firstName = cleaned_data.get('firstName')

    if not username:
        raise forms.ValidationError('Enter Username')

    if User.objects.filter(username=username).exists():
        raise forms.ValidationError("Username is taken by another one")

    if not email:
        raise forms.ValidationError('Enter E-Mail')

    if User.objects.filter(email=email).exists():
        raise forms.ValidationError("E-Mail is taken by another one")

    if not password:
        raise forms.ValidationError('Enter password')

    if not repeatPassword:
        raise forms.ValidationError('Repeat password')

    if password != repeatPassword:
        raise forms.ValidationError('Passwords are not equal')
</code>```

views.py

```<code>def register_view(request):
if request.method == 'POST':
    form = RegisterForm(request.POST)
    if form.is_valid():
        user = User.objects.create_user(username=request.POST['username'], email=request.POST['email'],
                                        password=request.POST['password'], first_name=request.POST['firstName'],
                                        last_name=request.POST['name'])

        user.save()

        # Get Created User from DB
        user = authenticate(request, username=request.POST['username'], password=request.POST['password'])
        if user:
            # LogIn (create Session etc...)
            login(request, user)

            # open user.html
            return render(request, 'web/user.html')
    return render(request, 'web/register.html', {'form': form})
else:
    form = RegisterForm()
    return render(request, 'web/register.html', {'form': form})
</code>```

答:
It seems that this message is just an information, that a weak password is used.
Thanks to Tenacious B for clarify this.</p>

Body:
im new at django and for learning i create a fantasy project. By testing my website i was been warned from my Chrome browser that i should change my password. The exact message is

Due to a data breach on a website or in an app your password was disclosed. Chrome recommends changing your password to 127.0.0.1:8000.

is there anything in my code that makes this data breach?

Thanks for helping!

forms.py

class RegisterForm(forms.Form):

username = forms.CharField(
    label='Benutzername',
    max_length=150,
    required=True,
    widget=forms.TextInput(
        attrs={
            'placeholder': 'Username',
        }
    )
)

email = forms.EmailField(
    label='E-Mail Adresse',
    max_length=254,
    required=True,
    widget=forms.EmailInput(
        attrs={
            'placeholder': 'email@exapmle.com',
        }
    )
)

password = forms.CharField(
    label='Passwort',
    max_length=254,
    required=True,
    widget=forms.PasswordInput(
        attrs={
            'placeholder': 'Password',
        }
    )
)

repeatPassword = forms.CharField(
    label='Passwort wiederholen',
    max_length=254, required=True,
    widget=forms.PasswordInput(
        attrs={
            'placeholder': 'Password',
        }
    )
)

name = forms.CharField(
    label='Nachname',
    max_length=150,
    required=False,
    widget=forms.TextInput(
        attrs={
            'placeholder': 'Last Name',
        }
    )
)

firstName = forms.CharField(
    label='Vorname',
    max_length=150,
    required=False,
    widget=forms.TextInput(
        attrs={
            'placeholder': 'First name',
        }
    )
)

def clean(self):
    cleaned_data = super(RegisterForm, self).clean()
    username = cleaned_data.get('username')
    email = cleaned_data.get('email')
    password = cleaned_data.get('password')
    repeatPassword = cleaned_data.get('repeatPassword')
    name = cleaned_data.get('name')
    firstName = cleaned_data.get('firstName')

    if not username:
        raise forms.ValidationError('Enter Username')

    if User.objects.filter(username=username).exists():
        raise forms.ValidationError("Username is taken by another one")

    if not email:
        raise forms.ValidationError('Enter E-Mail')

    if User.objects.filter(email=email).exists():
        raise forms.ValidationError("E-Mail is taken by another one")

    if not password:
        raise forms.ValidationError('Enter password')

    if not repeatPassword:
        raise forms.ValidationError('Repeat password')

    if password != repeatPassword:
        raise forms.ValidationError('Passwords are not equal')

views.py

def register_view(request):
if request.method == 'POST':
    form = RegisterForm(request.POST)
    if form.is_valid():
        user = User.objects.create_user(username=request.POST['username'], email=request.POST['email'],
                                        password=request.POST['password'], first_name=request.POST['firstName'],
                                        last_name=request.POST['name'])

        user.save()

        # Get Created User from DB
        user = authenticate(request, username=request.POST['username'], password=request.POST['password'])
        if user:
            # LogIn (create Session etc...)
            login(request, user)

            # open user.html
            return render(request, 'web/user.html')
    return render(request, 'web/register.html', {'form': form})
else:
    form = RegisterForm()
    return render(request, 'web/register.html', {'form': form})


问:
How to separate strings in a dataframe column based on a delimiter?
So, I have a dataframe which looks like this:

I want to separate the values in 'Filename' column into strings based on "-" and "." and also remove the extension name. Then I want to separate the values in 'Path' column into strings based on "\" and ":". How do I do this?

答:
It's not entirely clear what you're looking for here. But here's my best interpretation.

Setup:

```<code>df = pd.DataFrame({
    "Filename": ["doc-hi.txt", "oh-my-god.txt"],
    "Path": ["C:\asdf\asdf\asdf\kd.txt", "C:\asdcsc.docx"]
})
</code>```

Separate strings

```<code># "separate the values in 'Filename' column into strings based on '-' and '.' and also remove the extension name"
df["Filename_split"] = df["Filename"].apply(lambda _: os.path.splitext(_)[0]).str.split(r'\.|-')

# "separate the values in 'Path' column into strings based on '\' and ':'"
df["Path_split"] = df["Path"].str.split(r'\\|:')
</code>```

Intermediate Output

```<code>    Filename        Path                    Filename_split  Path_split
0   doc-hi.txt      C:sdf\sdf\sdf\kd.txt    [doc, hi]       [C, , asdf, asdf, asdf, kd.txt]
1   oh-my-god.txt   C:sdcsc.docx            [oh, my, god]   [C, sdcsc.docx]
</code>```

Combining tokens back together

To combine the list of strings back together into single strings, you str.join:

```<code>df['Filename_split'].str.join(' ')
df['Path_split'].str.join(' ')
</code>```

Body:
It's not entirely clear what you're looking for here. But here's my best interpretation.

Setup:

df = pd.DataFrame({
    "Filename": ["doc-hi.txt", "oh-my-god.txt"],
    "Path": ["C:\asdf\asdf\asdf\kd.txt", "C:\asdcsc.docx"]
})

Separate strings

# "separate the values in 'Filename' column into strings based on '-' and '.' and also remove the extension name"
df["Filename_split"] = df["Filename"].apply(lambda _: os.path.splitext(_)[0]).str.split(r'\.|-')

# "separate the values in 'Path' column into strings based on '\' and ':'"
df["Path_split"] = df["Path"].str.split(r'\\|:')

Intermediate Output

    Filename        Path                    Filename_split  Path_split
0   doc-hi.txt      C:sdf\sdf\sdf\kd.txt    [doc, hi]       [C, , asdf, asdf, asdf, kd.txt]
1   oh-my-god.txt   C:sdcsc.docx            [oh, my, god]   [C, sdcsc.docx]

Combining tokens back together

To combine the list of strings back together into single strings, you str.join:

df['Filename_split'].str.join(' ')
df['Path_split'].str.join(' ')


问:
How to disable "Leave site" Button for a non admin user in alfresco
I am currently working on the alfresco community edition 5.2.

Now i am working on customizing the header option for non admin user. Now i am trying to disable leave site button for the non admin user in alfresco.

So can anyone give me solution for this problem.

Thanks and regards,
Amar.

答:
It's easy to hide rather disabling the menu action.
You have to extend, share-header.get.js and you can use the below code.

```<code>if (!user.isAdmin) {
  widgetUtils.deleteObjectFromArray(model.jsonModel, "id", "HEADER_LEAVE_SITE");
}
</code>```

You can refer the below link also.
https://hub.alfresco.com/t5/alfresco-content-services-forum/disable-button-quot-leave-site-quot-from-the-header-on-alfresco/m-p/79956

HTH

Body:
It's easy to hide rather disabling the menu action.
You have to extend, share-header.get.js and you can use the below code.

if (!user.isAdmin) {
  widgetUtils.deleteObjectFromArray(model.jsonModel, "id", "HEADER_LEAVE_SITE");
}

You can refer the below link also.
https://hub.alfresco.com/t5/alfresco-content-services-forum/disable-button-quot-leave-site-quot-from-the-header-on-alfresco/m-p/79956

HTH


问:
Pragma no cache and javascript
Does the pragma no-cache mean the browser will not cache javascript scripts?

e.g.

Will the pragma no cache tag stop the browser from caching the jquery script?

答:
Actually, that depends on the browser used. For modern browsers you need to add Cache-Control and Expires headers as well.

```<code>response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
</code>```

See also:

How to control web page caching, across all browsers?

ContentLicense: CC BY-SA 3.0

Title: Pragma no cache and javascript

Body:
Actually, that depends on the browser used. For modern browsers you need to add Cache-Control and Expires headers as well.

response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);

See also:

How to control web page caching, across all browsers?


问:
How can you use a function pointer with argument in c?
How can you use this function pointer declaration?

```<code>int (* get_function(char c)) (int, int);
</code>```

I have three functions int function_a(int a, int b), int function_b(int a, int b) and int function_c(int a, int b). I want to use the above function pointer to call one of my functions conditionally based on c.

答:
Here is an example:

```<code>#include <stdio.h>

int function_a(int a, int b)
{
    printf("Inside function_a: %d %d\n", a, b);
    return a+b;
}

int function_b(int a, int b)
{
    printf("Inside function_b: %d %d\n", a, b);
    return a+b;
}

int function_c(int a, int b)
{
    printf("Inside function_c: %d %d\n", a, b);
    return a+b;
}

int function_whatever(int a, int b)
{
    printf("Inside function_whatever: %d %d\n", a, b);
    return a+b;
}

int (* get_function(char c)) (int, int)
{
    switch(c)
    {
        case 'A':
            return function_a;
        case 'B':
            return function_b;
        case 'C':
            return function_c;
    }
    return function_whatever;
}

int main(void) {
    get_function('B')(3, 5);
    return 0;
}
</code>```

get_function('B') returns a function pointer to function_b and get_function('B')(3, 5); also calls that function.

https://ideone.com/0kUp47

Body:
How can you use this function pointer declaration?

int (* get_function(char c)) (int, int);

I have three functions int function_a(int a, int b), int function_b(int a, int b) and int function_c(int a, int b). I want to use the above function pointer to call one of my functions conditionally based on c.

Body:
Here is an example:

#include <stdio.h>

int function_a(int a, int b)
{
    printf("Inside function_a: %d %d\n", a, b);
    return a+b;
}

int function_b(int a, int b)
{
    printf("Inside function_b: %d %d\n", a, b);
    return a+b;
}

int function_c(int a, int b)
{
    printf("Inside function_c: %d %d\n", a, b);
    return a+b;
}

int function_whatever(int a, int b)
{
    printf("Inside function_whatever: %d %d\n", a, b);
    return a+b;
}

int (* get_function(char c)) (int, int)
{
    switch(c)
    {
        case 'A':
            return function_a;
        case 'B':
            return function_b;
        case 'C':
            return function_c;
    }
    return function_whatever;
}

int main(void) {
    get_function('B')(3, 5);
    return 0;
}

get_function('B') returns a function pointer to function_b and get_function('B')(3, 5); also calls that function.

https://ideone.com/0kUp47


问:
How to properly declare a self-referencing template type?
How do I declare a templated type that refers to itself?

```<code>template <class T = Animal> class Animal
{
public:
    T getChild ();
}
</code>```

With this, I get a compiler error concerning a missing type specifier. I tried to forward-declare Animal, without success.

I am trying to impose a type constraint. A Lion can only have a Lion as a child, a Bear has a Bear, and so on.

EDIT

I'll post part of the actual class. It is a template for classes that can appear in a linked list:

```<code>template <class T = Linked<T> > class Linked
{
private:
    T* m_prev;
    T* m_next;
}
</code>```

I want to enforce that the class can only point to object of the same class (or a subclass).

答:
In this case, you need to specify some type parameter to Animal in your typename definition, or else it would be an "infinite recursion" in the type construction:</p>

```<code>template<class T> class Animal;//you'll need this forward declaration

template <class T = Animal<int> > class Animal //int is just an example
{
public:
    T getPrey ();
}
</code>```

Body:
How do I declare a templated type that refers to itself?

template <class T = Animal> class Animal
{
public:
    T getChild ();
}

With this, I get a compiler error concerning a missing type specifier. I tried to forward-declare Animal, without success.

I am trying to impose a type constraint. A Lion can only have a Lion as a child, a Bear has a Bear, and so on.

EDIT

I'll post part of the actual class. It is a template for classes that can appear in a linked list:

template <class T = Linked<T> > class Linked
{
private:
    T* m_prev;
    T* m_next;
}

I want to enforce that the class can only point to object of the same class (or a subclass).

Body:
In this case, you need to specify some type parameter to Animal in your typename definition, or else it would be an "infinite recursion" in the type construction:

template<class T> class Animal;//you'll need this forward declaration

template <class T = Animal<int> > class Animal //int is just an example
{
public:
    T getPrey ();
}


问:
express router test with multiple handlers
I am testing my guard middleware, but altough everything seems to be working fine my expect statement fails.

/// auth.test.js

```<code>const request = require('supertest');
const express = require('express');
const app = require('../../app');
const authMiddleware = require('./auth.middleware');

const mockRes = () => {
  const res = {};
  res.status = jest.fn().mockReturnValue(res);
  res.sendStatus = jest.fn().mockReturnValue(res);
  res.send = jest.fn().mockReturnValue(res);
  return res;
};

describe('Authorization', () => {
  const guardedRouter = express.Router();

  guardedRouter.get(
    '/guardedandauthenticated',
    [authMiddleware.authenticate, authMiddleware.authorize('admin')],
    (req, res, _next) => {
      console.log('seems to be working');
      res.status(200);
      console.log('res is 200000000');
    },
  );

  let accessToken = '';
  beforeAll(async () => {
    const res = await request(app).post('/auth/login').send({
      username: 'admin',
      password: 'admin',
    });
    expect(res.status).toBe(200);
    accessToken = res.body.accessToken;
  });

  it('should allow access to authorized roles', () => {
    const response = mockRes();
    // @ts-ignore
    guardedRouter.handle(
      {
        headers: { authorization: `Bearer ${accessToken}` },
        url: '/guardedandauthenticated',
        method: 'GET',
      },
      response,
    );
    // THIS EXPECTATION IS FAILED
    expect(response.status).toHaveBeenCalledWith(200);
  });
});
</code>```

/// auth.middleware.js

```<code>    module.exports.authorize = role => {
  return async (req, res, next) => {
    if (!req.user) {
      return res.status(403).send({
        message: 'Unauthorized! No token provided!',
      });
    }
    if (req.user.role === undefined) {
      const privileges = await userService.getUserPrivileges(req.user.id);
      req.user.role = privileges.map(f => f.privilege_name);
    }
    const userRoles = req.user.role;

    const rolesToCheck = Array.isArray(role) ? role : [role];
    if (!rolesToCheck.every(r => userRoles.includes(r))) {
      return res.status(403).send({
        message: `Unauthorized! Required privileges are: ${userRoles.toString()}`,
      });
    }
    return next();
  };
};
</code>```

/// jest outcome

```<code>   expect(jest.fn()).toHaveBeenCalledWith(...expected)

    Expected: 200

    Number of calls: 0
</code>```

I cleaned up the code, my similar assertions are successfull, and the code seems to be working fine, either the way I setup router is incorrect, or, actually I have no clue. Console messages in the router are on the jest output, so it works fine.
Thanks in Advance,

答:
well it turned out to be a jest issue, you need to tell jest that you are done.

```<code>  it('should allow access to authorized roles', async done => {
    const res = { statusCode: 100 };
    res.status = function (code) {
      res.statusCode = code;
      return res;
    };
    // @ts-ignore
    guardedRouter.handle(
      {
        headers: { authorization: `Bearer ${accessToken}` },
        url: '/guardedandauthenticated',
        method: 'GET',
      },
      res,
    );
    setTimeout(() => {
      done();
      expect(res.statusCode).toBe(200);
    }, 300);
  });
</code>```

so I added a done callback to test case, and checked value after the handler is done. This still does not look like an ideal solution. The thing is that, handle will call 3 functions, one of them is async, I could not get it to report correct without setting a timer. There should be a solution without the timer, can anyone help with that?

Body:
I am testing my guard middleware, but altough everything seems to be working fine my expect statement fails.

/// auth.test.js

const request = require('supertest');
const express = require('express');
const app = require('../../app');
const authMiddleware = require('./auth.middleware');

const mockRes = () => {
  const res = {};
  res.status = jest.fn().mockReturnValue(res);
  res.sendStatus = jest.fn().mockReturnValue(res);
  res.send = jest.fn().mockReturnValue(res);
  return res;
};

describe('Authorization', () => {
  const guardedRouter = express.Router();

  guardedRouter.get(
    '/guardedandauthenticated',
    [authMiddleware.authenticate, authMiddleware.authorize('admin')],
    (req, res, _next) => {
      console.log('seems to be working');
      res.status(200);
      console.log('res is 200000000');
    },
  );

  let accessToken = '';
  beforeAll(async () => {
    const res = await request(app).post('/auth/login').send({
      username: 'admin',
      password: 'admin',
    });
    expect(res.status).toBe(200);
    accessToken = res.body.accessToken;
  });

  it('should allow access to authorized roles', () => {
    const response = mockRes();
    // @ts-ignore
    guardedRouter.handle(
      {
        headers: { authorization: `Bearer ${accessToken}` },
        url: '/guardedandauthenticated',
        method: 'GET',
      },
      response,
    );
    // THIS EXPECTATION IS FAILED
    expect(response.status).toHaveBeenCalledWith(200);
  });
});

/// auth.middleware.js

    module.exports.authorize = role => {
  return async (req, res, next) => {
    if (!req.user) {
      return res.status(403).send({
        message: 'Unauthorized! No token provided!',
      });
    }
    if (req.user.role === undefined) {
      const privileges = await userService.getUserPrivileges(req.user.id);
      req.user.role = privileges.map(f => f.privilege_name);
    }
    const userRoles = req.user.role;

    const rolesToCheck = Array.isArray(role) ? role : [role];
    if (!rolesToCheck.every(r => userRoles.includes(r))) {
      return res.status(403).send({
        message: `Unauthorized! Required privileges are: ${userRoles.toString()}`,
      });
    }
    return next();
  };
};

/// jest outcome

   expect(jest.fn()).toHaveBeenCalledWith(...expected)

    Expected: 200

    Number of calls: 0

I cleaned up the code, my similar assertions are successfull, and the code seems to be working fine, either the way I setup router is incorrect, or, actually I have no clue. Console messages in the router are on the jest output, so it works fine.
Thanks in Advance,

Body:
well it turned out to be a jest issue, you need to tell jest that you are done.

  it('should allow access to authorized roles', async done => {
    const res = { statusCode: 100 };
    res.status = function (code) {
      res.statusCode = code;
      return res;
    };
    // @ts-ignore
    guardedRouter.handle(
      {
        headers: { authorization: `Bearer ${accessToken}` },
        url: '/guardedandauthenticated',
        method: 'GET',
      },
      res,
    );
    setTimeout(() => {
      done();
      expect(res.statusCode).toBe(200);
    }, 300);
  });

so I added a done callback to test case, and checked value after the handler is done. This still does not look like an ideal solution. The thing is that, handle will call 3 functions, one of them is async, I could not get it to report correct without setting a timer. There should be a solution without the timer, can anyone help with that?


问:
How to Solve 403 Error in Spring Boot Post Request
I am newbie in spring boot rest services. I have developed some rest api in spring boot using maven project.

I have successfully developed Get and Post Api. My GET Method working properly in postman and mobile. when i am trying to hit post method from postman its working properly but from mobile its gives 403 forbidden error.

This is my Configuration:

```<code>spring.datasource.url = jdbc:mysql://localhost/sampledb?useSSL=false
spring.datasource.username = te
spring.datasource.password = test
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
</code>```

Please Suggest me how to solve error.

答:
To build on the accepted answer

Many HTTP client libraries (eg Axios) implicitly set a Content-Type: JSON header for POST requests. In my case, I forgot to allow that header causing only POSTS to fail.

```<code>@Bean
CorsConfigurationSource corsConfigurationSource() {
    ...
    configuration.addAllowedHeader("Content-Type"); // <- ALLOW THIS HEADER
    ...
}
</code>```

Body:
I am newbie in spring boot rest services. I have developed some rest api in spring boot using maven project.

I have successfully developed Get and Post Api. My GET Method working properly in postman and mobile. when i am trying to hit post method from postman its working properly but from mobile its gives 403 forbidden error.

This is my Configuration:

spring.datasource.url = jdbc:mysql://localhost/sampledb?useSSL=false
spring.datasource.username = te
spring.datasource.password = test
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

Please Suggest me how to solve error.

Body:
To build on the accepted answer

Many HTTP client libraries (eg Axios) implicitly set a Content-Type: JSON header for POST requests. In my case, I forgot to allow that header causing only POSTS to fail.

@Bean
CorsConfigurationSource corsConfigurationSource() {
    ...
    configuration.addAllowedHeader("Content-Type"); // <- ALLOW THIS HEADER
    ...
}


问:
SQL query to pick all active employees and terminated employees only during a specific period
I have written a query to get both active and inactive employees from a table-

```<code>select papf.name,papf.empl_id,papf.assignment_status_type
from per_all_people_f papf,
per_periods_of_service ppos
where papf.person_id = ppos.person_id
AND (ppos.ACTUAL_TERMINATION_DATE is null or trunc(ACTUAL_TERMINATION_DATE) BETWEEN TO_CHAR (:from_date,
'YYYY-MM-DD') AND TO_CHAR (:TO_DATE, 'YYYY-MM-DD'))
AND ASSIGNMENT_STATUS <> 'Terminated - No Payroll'
</code>```

This query will fetch all ACTIVE and INACTIVE assignments(terminated-Payroll eligible). I want that the inactive assignments/terminated-Payroll eligible assignment status is only fetched for the date passed i.e. :from_date and :to_date along with all ACTIVE assignments.

I added a condition that actual_termination_date is between these dates to pick the Terminated-Payroll eligible or it is null for the active assignments but this query is fetching Terminated-Payroll eligible even when the actual_termination_date is not in those dates.

Just to add Terminated-Payroll eligible corresponds to INACTIVE IN papf.assignment_status_type

答:
You are using the TO_CHAR (:from_date,'YYYY-MM-DD'), You don't have to convert it to CHAR as you are comparing it against the date. (both :from_date and :to_date)

If :from_date is date then simply use the :from_date and if :from_date is a string then convert it to date and then use it as to_date(:from_date,'YYYY-MM-DD') -- applies to :to_date also

Body:
I have written a query to get both active and inactive employees from a table-

select papf.name,papf.empl_id,papf.assignment_status_type
from per_all_people_f papf,
per_periods_of_service ppos
where papf.person_id = ppos.person_id
AND (ppos.ACTUAL_TERMINATION_DATE is null or trunc(ACTUAL_TERMINATION_DATE) BETWEEN TO_CHAR (:from_date,
'YYYY-MM-DD') AND TO_CHAR (:TO_DATE, 'YYYY-MM-DD'))
AND ASSIGNMENT_STATUS <> 'Terminated - No Payroll'

This query will fetch all ACTIVE and INACTIVE assignments(terminated-Payroll eligible). I want that the inactive assignments/terminated-Payroll eligible assignment status is only fetched for the date passed i.e. :from_date and :to_date along with all ACTIVE assignments.

I added a condition that actual_termination_date is between these dates to pick the Terminated-Payroll eligible or it is null for the active assignments but this query is fetching Terminated-Payroll eligible even when the actual_termination_date is not in those dates.

Just to add Terminated-Payroll eligible corresponds to INACTIVE IN papf.assignment_status_type


问:
error NG6002: Appears in the NgModule.imports of AppModule, but could not be resolved to an NgModule class
First time using firestore and I'm getting this error. It seems to be a problem with Ivy, from my research. I don't have a lot of experience modifying tsconfig.app.json, which is the direction I've been pointed to, following other answers.

The only thing I was able to modify from the original project was to use Angular Fire 6 instead of 5, which I had done initially to follow a tutorial.

Here's package.json:

{
  "name": "language",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~9.0.1",
    "@angular/cdk": "^9.0.0",
    "@angular/common": "~9.0.1",
    "@angular/compiler": "~9.0.1",
    "@angular/core": "~9.0.1",
    "@angular/fire": "^6.0.0-rc.1",
    "@angular/flex-layout": "^9.0.0-beta.29",
    "@angular/forms": "~9.0.1",
    "@angular/material": "^9.0.0",
    "@angular/platform-browser": "~9.0.1",
    "@angular/platform-browser-dynamic": "~9.0.1",
    "@angular/router": "~9.0.1",
    "firebase": "^7.8.2",
    "rxjs": "~6.5.4",
    "rxjs-compat": "^6.5.4",
    "tslib": "^1.10.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.900.2",
    "@angular/cli": "~9.0.2",
    "@angular/compiler-cli": "~9.0.1",
    "@angular/language-service": "~9.0.1",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.3.8",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.4.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.1.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.15.0",
    "typescript": "~3.7.5",
    "@angular-devkit/architect": "^0.900.0-0 || ^0.900.0",
    "firebase-tools": "^7.12.1",
    "fuzzy": "^0.1.3",
    "inquirer": "^6.2.2",
    "inquirer-autocomplete-prompt": "^1.0.1"
  }
}
```
<p>angular.json</p>
<pre class="lang-json prettyprint-override"><code>{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "language": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/language",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
              "src/styles.scss"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "language:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "language:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "language:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
              "src/styles.scss"
            ],
            "scripts": []
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "language:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "language:serve:production"
            }
          }
        },
        "deploy": {
          "builder": "@angular/fire:deploy",
          "options": {}
        }
      }
    }
  },
  "defaultProject": "language"
}
</code>```

tsconfig.app.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": [],

  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ],
  "exclude": [
    "src/test.ts",
    "src/**/*.spec.ts"
  ]
}
```

Thanks!

答:
This issue will be fixed by adding the postinstall script below in your package.json.

It will be run after a npm install.

```<code>"scripts": {
   "postinstall": "ngcc"
}
</code>```

Post adding the above code, run npm install

This works for me when upgrading to Angular 9+

Body:
First time using firestore and I'm getting this error. It seems to be a problem with Ivy, from my research. I don't have a lot of experience modifying tsconfig.app.json, which is the direction I've been pointed to, following other answers.

The only thing I was able to modify from the original project was to use Angular Fire 6 instead of 5, which I had done initially to follow a tutorial.

Here's package.json:

{
  "name": "language",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~9.0.1",
    "@angular/cdk": "^9.0.0",
    "@angular/common": "~9.0.1",
    "@angular/compiler": "~9.0.1",
    "@angular/core": "~9.0.1",
    "@angular/fire": "^6.0.0-rc.1",
    "@angular/flex-layout": "^9.0.0-beta.29",
    "@angular/forms": "~9.0.1",
    "@angular/material": "^9.0.0",
    "@angular/platform-browser": "~9.0.1",
    "@angular/platform-browser-dynamic": "~9.0.1",
    "@angular/router": "~9.0.1",
    "firebase": "^7.8.2",
    "rxjs": "~6.5.4",
    "rxjs-compat": "^6.5.4",
    "tslib": "^1.10.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.900.2",
    "@angular/cli": "~9.0.2",
    "@angular/compiler-cli": "~9.0.1",
    "@angular/language-service": "~9.0.1",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.3.8",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.4.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.1.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.15.0",
    "typescript": "~3.7.5",
    "@angular-devkit/architect": "^0.900.0-0 || ^0.900.0",
    "firebase-tools": "^7.12.1",
    "fuzzy": "^0.1.3",
    "inquirer": "^6.2.2",
    "inquirer-autocomplete-prompt": "^1.0.1"
  }
}

angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "language": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/language",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
              "src/styles.scss"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "language:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "language:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "language:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
              "src/styles.scss"
            ],
            "scripts": []
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "language:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "language:serve:production"
            }
          }
        },
        "deploy": {
          "builder": "@angular/fire:deploy",
          "options": {}
        }
      }
    }
  },
  "defaultProject": "language"
}

tsconfig.app.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": [],

  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ],
  "exclude": [
    "src/test.ts",
    "src/**/*.spec.ts"
  ]
}

Thanks!

Body:
This issue will be fixed by adding the postinstall script below in your package.json.

It will be run after a npm install.

"scripts": {
   "postinstall": "ngcc"
}

Post adding the above code, run npm install

This works for me when upgrading to Angular 9+


问:
Sping retry throws RetryExhaustedException when exception is not included in @Retryable
I am using spring-retry 1.2.5. In my code I am using @Retryable and @CircuitBreaker annotation but whenever there is an exception which is not mentioned in include attribute I am getting RetryExhaustedException instead of the thrown checked exception.

I found that we need to set the throwLastExceptionOnExhausted to true in RetryTemplate.

I added a RetryTemplate bean in the config class and set the property to true but at runtime

the created bean is not getting used.
Basically @Retryable annotation is not using the bean which I created in configuration.

How can I set throwLastExceptionOnExhausted property when using @Retryable annotation ?

答:
There are a couple of options.

Wire up your own interceptor bean and use it in the @Retryable interceptor property.

Add a @Recover method and re-throw the exception from there.

2 is probably the easiest.


问:
Kick command with reason
I created a kick command with reason, but it doesn't kick the member, I don't have any errors...
Also, why when I send the command, it deletes it?

I tried to fix it myself, but still doesn't work. Thanks for your help.

Here my code:

```<code>client.on('message', message => {
  if(message.content.startsWith(prefix + "kick")) {
     if(message.channel.type === 'DM') {
    message.channel.send('This command can use only in guide');
    return;
  };
  if(!message.member.hasPermission('KICK_MEMBERS')) {
    const KickEmbed = new Discord.MessageEmbed()
    .setColor("YELLOW")
    .setAuthor(message.author.username)
    .setDescription("Sorry, but you don't have the permission to use the kick command.")
    message.channel.send(KickEmbed);
    return;
  };
  let mentionMember = message.mentions.members.first();
  if(!mentionMember) {
    const ErrEmbed = new Discord.MessageEmbed()
    .setColor('YELLOW')
    .setAuthor(message.author.username)
    .setDescription('**Usage:** `y!kick <@user> or ID` You need to mention an user!')
    message.channel.send(ErrEmbed);
                      return;
                     };
        let args = message.content.slice(prefix.length).trim().split(/ +/g);
    if(!args.lenght) {
      const ReasonError = new Discord.MessageEmbed()
      .setColor('YELLOW')
      .setAuthor(message.author.username)
      .setDescription('Before kicking this member, you need to provide a reason of your kick.')
      message.channel.send(ReasonError)
      return;
    };
  let authorHighestRole = message.member.roles.highest.position;
  let mentionHighestRole = mentionMember.roles.highest.position;
  if(mentionHighestRole >= authorHighestRole) {
    message.channel.send('You can`t kick members with equal or higher position');
    return;
  };
  if(!mentionMember.kickable) {
    message.channel.send('I have no permissions to kick this user');
    return
  };
  mentionMember.kick()
    .then(() => message.channel.send(`Kicked ${mentionMember.tag} with reason: ${args}`))
    .catch(console.error);
}
          }
);
</code>```

答:
Should look at docs before posting:

https://discord.js.org/#/docs/main/stable/class/GuildMember?scrollTo=kick

But anyways:

<Member>.kick(Reason), it's just a string you pass in.

Also args looks like an array so you can't just use args inside of a string, try args.join(" "). (Inside of message.channel.send("Kicked..."))

All in all here's the change:

So mentionMember.kick() => mentionMember.kick(args.join(" "))

Title: Kick command with reason

Body:
I created a kick command with reason, but it doesn't kick the member, I don't have any errors...
Also, why when I send the command, it deletes it?

I tried to fix it myself, but still doesn't work. Thanks for your help.

Here my code:

client.on('message', message => {
  if(message.content.startsWith(prefix + "kick")) {
     if(message.channel.type === 'DM') {
    message.channel.send('This command can use only in guide');
    return;
  };
  if(!message.member.hasPermission('KICK_MEMBERS')) {
    const KickEmbed = new Discord.MessageEmbed()
    .setColor("YELLOW")
    .setAuthor(message.author.username)
    .setDescription("Sorry, but you don't have the permission to use the kick command.")
    message.channel.send(KickEmbed);
    return;
  };
  let mentionMember = message.mentions.members.first();
  if(!mentionMember) {
    const ErrEmbed = new Discord.MessageEmbed()
    .setColor('YELLOW')
    .setAuthor(message.author.username)
    .setDescription('**Usage:** `y!kick <@user> or ID` You need to mention an user!')
    message.channel.send(ErrEmbed);
                      return;
                     };
        let args = message.content.slice(prefix.length).trim().split(/ +/g);
    if(!args.lenght) {
      const ReasonError = new Discord.MessageEmbed()
      .setColor('YELLOW')
      .setAuthor(message.author.username)
      .setDescription('Before kicking this member, you need to provide a reason of your kick.')
      message.channel.send(ReasonError)
      return;
    };
  let authorHighestRole = message.member.roles.highest.position;
  let mentionHighestRole = mentionMember.roles.highest.position;
  if(mentionHighestRole >= authorHighestRole) {
    message.channel.send('You can`t kick members with equal or higher position');
    return;
  };
  if(!mentionMember.kickable) {
    message.channel.send('I have no permissions to kick this user');
    return
  };
  mentionMember.kick()
    .then(() => message.channel.send(`Kicked ${mentionMember.tag} with reason: ${args}`))
    .catch(console.error);
}
          }
);


问:
Permutation tree not making sense with the code
I watched a youtube video where this basic permutation tree was shown. If you look at this bit of code:

```<code>    function recursion(input, set = [], result = []) {
        if (!input.length) {
           result.push([...set].join(''));
         }

        for (let i = 0; i < input.length; i++) {
            const newArr = input.filter((n, index) => index !== i);
            set.push(input[i]);
            recursion(newArr, set, result);
            set.pop();
         }
         return result.join(', ');
}
</code>```

you can see that the base case (if statement) is at the top before the parameter nums is filtered. So, my whole question is how the tree and the code makes sense because for me the code would remove one too many digits from the set array. Becuase it pops an item of when returning and doesn't it return more than two times?

答:
Does this log add clarity?

```<code>/ entering recursion with input = [1,2,3], set = [], result = []
| looping, i = 0
| adding  1 to set
|   / entering recursion with input = [2,3], set = [1], result = []
|   | looping, i = 0
|   | adding  2 to set
|   |   / entering recursion with input = [3], set = [1,2], result = []
|   |   | looping, i = 0
|   |   | adding  3 to set
|   |   |   / entering recursion with input = [], set = [1,2,3], result = []
|   |   |   | adding 123 to result
|   |   |   \ returning [123]
|   |   | removing  3 from set
|   |   \ returning [123]
|   | removing  2 from set
|   | looping, i = 1
|   | adding  3 to set
|   |   / entering recursion with input = [2], set = [1,3], result = [123]
|   |   | looping, i = 0
|   |   | adding  2 to set
|   |   |   / entering recursion with input = [], set = [1,3,2], result = [123]
|   |   |   | adding 132 to result
|   |   |   \ returning [123,132]
|   |   | removing  2 from set
|   |   \ returning [123,132]
|   | removing  3 from set
|   \ returning [123,132]
| removing  1 from set
| looping, i = 1
| adding  2 to set
|   / entering recursion with input = [1,3], set = [2], result = [123,132]
|   | looping, i = 0
|   | adding  1 to set
|   |   / entering recursion with input = [3], set = [2,1], result = [123,132]
|   |   | looping, i = 0
|   |   | adding  3 to set
|   |   |   / entering recursion with input = [], set = [2,1,3], result = [123,132]
|   |   |   | adding 213 to result
|   |   |   \ returning [123,132,213]
|   |   | removing  3 from set
|   |   \ returning [123,132,213]
|   | removing  1 from set
|   | looping, i = 1
|   | adding  3 to set
|   |   / entering recursion with input = [1], set = [2,3], result = [123,132,213]
|   |   | looping, i = 0
|   |   | adding  1 to set
|   |   |   / entering recursion with input = [], set = [2,3,1], result = [123,132,213]
|   |   |   | adding 231 to result
|   |   |   \ returning [123,132,213,231]
|   |   | removing  1 from set
|   |   \ returning [123,132,213,231]
|   | removing  3 from set
|   \ returning [123,132,213,231]
| removing  2 from set
| looping, i = 2
| adding  3 to set
|   / entering recursion with input = [1,2], set = [3], result = [123,132,213,231]
|   | looping, i = 0
|   | adding  1 to set
|   |   / entering recursion with input = [2], set = [3,1], result = [123,132,213,231]
|   |   | looping, i = 0
|   |   | adding  2 to set
|   |   |   / entering recursion with input = [], set = [3,1,2], result = [123,132,213,231]
|   |   |   | adding 312 to result
|   |   |   \ returning [123,132,213,231,312]
|   |   | removing  2 from set
|   |   \ returning [123,132,213,231,312]
|   | removing  1 from set
|   | looping, i = 1
|   | adding  2 to set
|   |   / entering recursion with input = [1], set = [3,2], result = [123,132,213,231,312]
|   |   | looping, i = 0
|   |   | adding  1 to set
|   |   |   / entering recursion with input = [], set = [3,2,1], result = [123,132,213,231,312]
|   |   |   | adding 321 to result
|   |   |   \ returning [123,132,213,231,312,321]
|   |   | removing  1 from set
|   |   \ returning [123,132,213,231,312,321]
|   | removing  2 from set
|   \ returning [123,132,213,231,312,321]
| removing  3 from set
\ returning [123,132,213,231,312,321]
</code>```

You can see how I added the logging to your code in this snippet:

const log = (depth, message) =>
  console .log ('|   '.repeat (depth)  + message)

function recursion(input, set = [], result = [], depth = 0) {
    log (depth, `/ entering recursion with input = [${input}], set = [${set}], result = [${result}]`)
    if (!input.length) {
        log (depth, `| adding ${[...set].join('')} to result`)
        result.push([...set].join(''));
     }

    for (let i = 0; i < input.length; i++) {
        log (depth, `| looping, i = ${i}`)
        const newArr = input.filter((n, index) => index !== i);
        log (depth, `| adding  ${input[i]} to set` )
        set.push(input[i]);
        recursion(newArr, set, result, depth + 1);
        log (depth, `| removing  ${input[i]} from set` )
        set.pop();
    }
    log (depth, `\\ returning [${result}]`)
    return result.join(', ');
}

console .log (recursion([1, 2, 3]))```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.as-console-wrapper {min-height: 100% !important; top: 0}</code>```

(but the console output there is limited to the last 50 lines.)

Body:
I watched a youtube video where this basic permutation tree was shown. If you look at this bit of code:

    function recursion(input, set = [], result = []) {
        if (!input.length) {
           result.push([...set].join(''));
         }

        for (let i = 0; i < input.length; i++) {
            const newArr = input.filter((n, index) => index !== i);
            set.push(input[i]);
            recursion(newArr, set, result);
            set.pop();
         }
         return result.join(', ');
}

you can see that the base case (if statement) is at the top before the parameter nums is filtered. So, my whole question is how the tree and the code makes sense because for me the code would remove one too many digits from the set array. Becuase it pops an item of when returning and doesn't it return more than two times?

Body:
Does this log add clarity?

/ entering recursion with input = [1,2,3], set = [], result = []
| looping, i = 0
| adding  1 to set
|   / entering recursion with input = [2,3], set = [1], result = []
|   | looping, i = 0
|   | adding  2 to set
|   |   / entering recursion with input = [3], set = [1,2], result = []
|   |   | looping, i = 0
|   |   | adding  3 to set
|   |   |   / entering recursion with input = [], set = [1,2,3], result = []
|   |   |   | adding 123 to result
|   |   |   \ returning [123]
|   |   | removing  3 from set
|   |   \ returning [123]
|   | removing  2 from set
|   | looping, i = 1
|   | adding  3 to set
|   |   / entering recursion with input = [2], set = [1,3], result = [123]
|   |   | looping, i = 0
|   |   | adding  2 to set
|   |   |   / entering recursion with input = [], set = [1,3,2], result = [123]
|   |   |   | adding 132 to result
|   |   |   \ returning [123,132]
|   |   | removing  2 from set
|   |   \ returning [123,132]
|   | removing  3 from set
|   \ returning [123,132]
| removing  1 from set
| looping, i = 1
| adding  2 to set
|   / entering recursion with input = [1,3], set = [2], result = [123,132]
|   | looping, i = 0
|   | adding  1 to set
|   |   / entering recursion with input = [3], set = [2,1], result = [123,132]
|   |   | looping, i = 0
|   |   | adding  3 to set
|   |   |   / entering recursion with input = [], set = [2,1,3], result = [123,132]
|   |   |   | adding 213 to result
|   |   |   \ returning [123,132,213]
|   |   | removing  3 from set
|   |   \ returning [123,132,213]
|   | removing  1 from set
|   | looping, i = 1
|   | adding  3 to set
|   |   / entering recursion with input = [1], set = [2,3], result = [123,132,213]
|   |   | looping, i = 0
|   |   | adding  1 to set
|   |   |   / entering recursion with input = [], set = [2,3,1], result = [123,132,213]
|   |   |   | adding 231 to result
|   |   |   \ returning [123,132,213,231]
|   |   | removing  1 from set
|   |   \ returning [123,132,213,231]
|   | removing  3 from set
|   \ returning [123,132,213,231]
| removing  2 from set
| looping, i = 2
| adding  3 to set
|   / entering recursion with input = [1,2], set = [3], result = [123,132,213,231]
|   | looping, i = 0
|   | adding  1 to set
|   |   / entering recursion with input = [2], set = [3,1], result = [123,132,213,231]
|   |   | looping, i = 0
|   |   | adding  2 to set
|   |   |   / entering recursion with input = [], set = [3,1,2], result = [123,132,213,231]
|   |   |   | adding 312 to result
|   |   |   \ returning [123,132,213,231,312]
|   |   | removing  2 from set
|   |   \ returning [123,132,213,231,312]
|   | removing  1 from set
|   | looping, i = 1
|   | adding  2 to set
|   |   / entering recursion with input = [1], set = [3,2], result = [123,132,213,231,312]
|   |   | looping, i = 0
|   |   | adding  1 to set
|   |   |   / entering recursion with input = [], set = [3,2,1], result = [123,132,213,231,312]
|   |   |   | adding 321 to result
|   |   |   \ returning [123,132,213,231,312,321]
|   |   | removing  1 from set
|   |   \ returning [123,132,213,231,312,321]
|   | removing  2 from set
|   \ returning [123,132,213,231,312,321]
| removing  3 from set
\ returning [123,132,213,231,312,321]

You can see how I added the logging to your code in this snippet:

const log = (depth, message) =>
  console .log ('|   '.repeat (depth)  + message)

function recursion(input, set = [], result = [], depth = 0) {
    log (depth, `/ entering recursion with input = [${input}], set = [${set}], result = [${result}]`)
    if (!input.length) {
        log (depth, `| adding ${[...set].join('')} to result`)
        result.push([...set].join(''));
     }

    for (let i = 0; i < input.length; i++) {
        log (depth, `| looping, i = ${i}`)
        const newArr = input.filter((n, index) => index !== i);
        log (depth, `| adding  ${input[i]} to set` )
        set.push(input[i]);
        recursion(newArr, set, result, depth + 1);
        log (depth, `| removing  ${input[i]} from set` )
        set.pop();
    }
    log (depth, `\\ returning [${result}]`)
    return result.join(', ');
}

console .log (recursion([1, 2, 3]))

.as-console-wrapper {min-height: 100% !important; top: 0}

(but the console output there is limited to the last 50 lines.)


问:
omit twice nested property from 'this'
I'm trying to add a method that removes an internal property from the type of an object and due to a complex base class that I cant change I have the following problem:
I wrote a method that is supposed to cast out a cast in property (in this case, name)
but the property ceo.name remains available to access.
I believe this happens because adding a type without the ceo name property to this just takes the largest denominator
i.e {name:string} & {} == {name:string}

is there even a way to solve this?

```<code>class Company {
    ceo: {}
    addCeoNameType() {
        return this as this & {
            ceo: {
                name: string;
            }
        }
    }
    removeCeoNameType() {
        const ceoForType: this['ceo'] = null;
        return this as this & {
            ceo: Omit<typeof ceoForType, 'name'>;
        }
    }
}

class Foo {
    bar() {
        const catsInc = new Company();
        const catsIncWithCeoName = catsInc.addCeoNameType();
        catsIncWithCeoName.ceo.name;
        catsIncWithCeoName.removeCeoNameType().ceo.name;
    }
}
</code>```

答:
Maybe you could do it like that:</p>

```<code>type Ceo = { name: string };

class Company {
    addCeoNameType() {
        return this as this & {
            ceo: Ceo
        }
    }
    removeCeoNameType() {
        return this as unknown as Omit<this, 'ceo'> & { ceo: Omit<Ceo, 'name'> } ;
    }
}

class Foo {
    bar() {
        const catsInc = new Company();
        const catsIncWithCeoName = catsInc.addCeoNameType();
        catsIncWithCeoName.ceo.name;
        catsIncWithCeoName.removeCeoNameType().ceo.name;
                                                // ^ fails here
    }
}
</code>```

Title: omit twice nested property from 'this'

Body:
I'm trying to add a method that removes an internal property from the type of an object and due to a complex base class that I cant change I have the following problem:
I wrote a method that is supposed to cast out a cast in property (in this case, name)
but the property ceo.name remains available to access.
I believe this happens because adding a type without the ceo name property to this just takes the largest denominator
i.e {name:string} & {} == {name:string}

is there even a way to solve this?

class Company {
    ceo: {}
    addCeoNameType() {
        return this as this & {
            ceo: {
                name: string;
            }
        }
    }
    removeCeoNameType() {
        const ceoForType: this['ceo'] = null;
        return this as this & {
            ceo: Omit<typeof ceoForType, 'name'>;
        }
    }
}

class Foo {
    bar() {
        const catsInc = new Company();
        const catsIncWithCeoName = catsInc.addCeoNameType();
        catsIncWithCeoName.ceo.name;
        catsIncWithCeoName.removeCeoNameType().ceo.name;
    }
}

Body:
Maybe you could do it like that:

type Ceo = { name: string };

class Company {
    addCeoNameType() {
        return this as this & {
            ceo: Ceo
        }
    }
    removeCeoNameType() {
        return this as unknown as Omit<this, 'ceo'> & { ceo: Omit<Ceo, 'name'> } ;
    }
}

class Foo {
    bar() {
        const catsInc = new Company();
        const catsIncWithCeoName = catsInc.addCeoNameType();
        catsIncWithCeoName.ceo.name;
        catsIncWithCeoName.removeCeoNameType().ceo.name;
                                                // ^ fails here
    }
}


问:
Making join condition more exclusive causes query to hang
Sorry for the wall of SQL, but I am having some problems with the query below. It seems to never finish executing (it runs for a few minutes, then I kill it). The weird thing is that if I change the join condition for the StudentTestsPre table from TestInstances.fkSchoolYearID = (TestInstancesPre.fkSchoolYearID + 1) to TestInstances.fkSchoolYearID > TestInstancesPre.fkSchoolYearID, then the query returns instantly. How could using a more exclusive join condition cause my query to hang? Seems like that should make the query faster, if anything.

Any ideas?

```<code>            SELECT *
        FROM TestInstances
        INNER JOIN StudentTests on StudentTests.fkTestInstanceID = TestInstances.pkTestInstanceID
                                    AND StudentTests.pkStudentTestID IN (SELECT * FROM @tempTests)
        INNER JOIN TestInstances TestInstancesPre ON TestInstances.fkSchoolYearID = (TestInstancesPre.fkSchoolYearID + 1)
                                        AND TestInstancesPre.fkTestTypeID = 1 AND TestInstances.fkTestTypeID = 1
        INNER JOIN StudentTests StudentTestsPre on StudentTestsPre.fkTestInstanceID = TestInstancesPre.pkTestInstanceID
                                        AND StudentTests.fkStudentID = StudentTestsPre.fkStudentID
        INNER JOIN StudentScores_Subject s ON s.fkStudentTestID = StudentTests.pkStudentTestID
                                        AND s.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(@strAcceptableStrands, N','))  AND fkTestTypeID = 1)
                                        AND s.fkScoreTypeID = 3
        INNER JOIN StudentScores_Subject sPre ON sPre.fkStudentTestID = StudentTestsPre.pkStudentTestID
                                        AND sPre.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(@strAcceptableStrands, N','))  AND fkTestTypeID = 1)
                                        AND sPre.fkScoreTypeID = 3
        INNER JOIN MM_Test_PL_SS_Ranges r ON r.fkTest_SubjectID = s.fkTest_SubjectID
                                        AND r.fkSchoolYearID = TestInstances.fkSchoolYearID
                                        AND r.fkTestTypeID = TestInstances.fkTestTypeID
                                        AND (r.fkGradeID = StudentTests.fkGradeID OR r.fkGradeID = 99)
        INNER JOIN MM_Test_PL_SS_Ranges rPre ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
                                        AND rPre.fkSchoolYearID = TestInstancesPre.fkSchoolYearID
                                        AND rPre.fkTestTypeID = TestInstancesPre.fkTestTypeID
                                        AND (rPre.fkGradeID = StudentTestsPre.fkGradeID OR rPre.fkGradeID = 99)
        INNER JOIN StudentScores_Subject s2 ON s2.fkStudentTestID = StudentTests.pkStudentTestID
                                        AND s2.fkTest_SubjectID = s.fkTest_SubjectID
                                        AND s2.fkScoreTypeID = 2
        INNER JOIN StudentScores_Subject sPre2 ON sPre2.fkStudentTestID = StudentTestsPre.pkStudentTestID
                                        AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
                                        AND sPre2.fkScoreTypeID = 2
        INNER JOIN Students on Students.pkStudentID = StudentTests.fkStudentID
</code>```

thanks for the help!

For SO, here's the above script with alternative formatting & short aliases:

```<code>SELECT *
FROM TestInstances

  INNER JOIN StudentTests st
     ON st.fkTestInstanceID = ti.pkTestInstanceID
    AND st.pkStudentTestID IN (SELECT * FROM @tempTests)

  INNER JOIN TestInstances tiPre
     ON ti.fkSchoolYearID = (tiPre.fkSchoolYearID + 1)
    AND tiPre.fkTestTypeID = 1 AND ti.fkTestTypeID = 1

  INNER JOIN StudentTests stPre
     ON stPre.fkTestInstanceID = tiPre.pkTestInstanceID
    AND st.fkStudentID = stPre.fkStudentID

  INNER JOIN StudentScores_Subject s
     ON s.fkStudentTestID = st.pkStudentTestID
    AND s.fkTest_SubjectID IN (
          SELECT pkTestSubjectID
          FROM MM_Test_Subjects
          WHERE fkCSTStrandID IN (
                  SELECT number FROM itot(@strAcceptableStrands, N','))
            AND fkTestTypeID = 1)
    AND s.fkScoreTypeID = 3

  INNER JOIN StudentScores_Subject sPre
     ON sPre.fkStudentTestID = stPre.pkStudentTestID
    AND sPre.fkTest_SubjectID IN (
          SELECT pkTestSubjectID
          FROM MM_Test_Subjects
          WHERE fkCSTStrandID IN (
                  SELECT number FROM itot(@strAcceptableStrands, N','))
            AND fkTestTypeID = 1)
    AND sPre.fkScoreTypeID = 3

  INNER JOIN MM_Test_PL_SS_Ranges r
     ON r.fkTest_SubjectID = s.fkTest_SubjectID
    AND r.fkSchoolYearID = ti.fkSchoolYearID
    AND r.fkTestTypeID = ti.fkTestTypeID
    AND (r.fkGradeID = st.fkGradeID OR r.fkGradeID = 99)

  INNER JOIN MM_Test_PL_SS_Ranges rPre
     ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
    AND rPre.fkSchoolYearID = tiPre.fkSchoolYearID
    AND rPre.fkTestTypeID = tiPre.fkTestTypeID
    AND (rPre.fkGradeID = stPre.fkGradeID OR rPre.fkGradeID = 99)

  INNER JOIN StudentScores_Subject s2
     ON s2.fkStudentTestID = st.pkStudentTestID
    AND s2.fkTest_SubjectID = s.fkTest_SubjectID
    AND s2.fkScoreTypeID = 2

  INNER JOIN StudentScores_Subject sPre2
     ON sPre2.fkStudentTestID = stPre.pkStudentTestID
    AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
    AND sPre2.fkScoreTypeID = 2

  INNER JOIN Students
     ON Students.pkStudentID = st.fkStudentID
</code>```

答:
Take a look at your execution plan.  My guess is that doing the calculation in the join aka (TestInstancesPre.fkSchoolYearID + 1) is causing indexes not be used correctly.  An easy way to test this would be to change your join to:

```<code>TestInstances.fkSchoolYearID = TestInstancesPre.fkSchoolYearID
</code>```

I have seen performance go way down when doing funky stuff in a join.  Things like:

```<code>ON t1.column1 = ISNULL(t2.myColumn, 1)
</code>```

I believe this is because the query becomes non-sargable.  Take a look at this SO post for more details on that.

Body:
Sorry for the wall of SQL, but I am having some problems with the query below. It seems to never finish executing (it runs for a few minutes, then I kill it). The weird thing is that if I change the join condition for the StudentTestsPre table from TestInstances.fkSchoolYearID = (TestInstancesPre.fkSchoolYearID + 1) to TestInstances.fkSchoolYearID > TestInstancesPre.fkSchoolYearID, then the query returns instantly. How could using a more exclusive join condition cause my query to hang? Seems like that should make the query faster, if anything.

Any ideas?

            SELECT *
        FROM TestInstances
        INNER JOIN StudentTests on StudentTests.fkTestInstanceID = TestInstances.pkTestInstanceID
                                    AND StudentTests.pkStudentTestID IN (SELECT * FROM @tempTests)
        INNER JOIN TestInstances TestInstancesPre ON TestInstances.fkSchoolYearID = (TestInstancesPre.fkSchoolYearID + 1)
                                        AND TestInstancesPre.fkTestTypeID = 1 AND TestInstances.fkTestTypeID = 1
        INNER JOIN StudentTests StudentTestsPre on StudentTestsPre.fkTestInstanceID = TestInstancesPre.pkTestInstanceID
                                        AND StudentTests.fkStudentID = StudentTestsPre.fkStudentID
        INNER JOIN StudentScores_Subject s ON s.fkStudentTestID = StudentTests.pkStudentTestID
                                        AND s.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(@strAcceptableStrands, N','))  AND fkTestTypeID = 1)
                                        AND s.fkScoreTypeID = 3
        INNER JOIN StudentScores_Subject sPre ON sPre.fkStudentTestID = StudentTestsPre.pkStudentTestID
                                        AND sPre.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(@strAcceptableStrands, N','))  AND fkTestTypeID = 1)
                                        AND sPre.fkScoreTypeID = 3
        INNER JOIN MM_Test_PL_SS_Ranges r ON r.fkTest_SubjectID = s.fkTest_SubjectID
                                        AND r.fkSchoolYearID = TestInstances.fkSchoolYearID
                                        AND r.fkTestTypeID = TestInstances.fkTestTypeID
                                        AND (r.fkGradeID = StudentTests.fkGradeID OR r.fkGradeID = 99)
        INNER JOIN MM_Test_PL_SS_Ranges rPre ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
                                        AND rPre.fkSchoolYearID = TestInstancesPre.fkSchoolYearID
                                        AND rPre.fkTestTypeID = TestInstancesPre.fkTestTypeID
                                        AND (rPre.fkGradeID = StudentTestsPre.fkGradeID OR rPre.fkGradeID = 99)
        INNER JOIN StudentScores_Subject s2 ON s2.fkStudentTestID = StudentTests.pkStudentTestID
                                        AND s2.fkTest_SubjectID = s.fkTest_SubjectID
                                        AND s2.fkScoreTypeID = 2
        INNER JOIN StudentScores_Subject sPre2 ON sPre2.fkStudentTestID = StudentTestsPre.pkStudentTestID
                                        AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
                                        AND sPre2.fkScoreTypeID = 2
        INNER JOIN Students on Students.pkStudentID = StudentTests.fkStudentID

thanks for the help!

For SO, here's the above script with alternative formatting & short aliases:

SELECT *
FROM TestInstances

  INNER JOIN StudentTests st
     ON st.fkTestInstanceID = ti.pkTestInstanceID
    AND st.pkStudentTestID IN (SELECT * FROM @tempTests)

  INNER JOIN TestInstances tiPre
     ON ti.fkSchoolYearID = (tiPre.fkSchoolYearID + 1)
    AND tiPre.fkTestTypeID = 1 AND ti.fkTestTypeID = 1

  INNER JOIN StudentTests stPre
     ON stPre.fkTestInstanceID = tiPre.pkTestInstanceID
    AND st.fkStudentID = stPre.fkStudentID

  INNER JOIN StudentScores_Subject s
     ON s.fkStudentTestID = st.pkStudentTestID
    AND s.fkTest_SubjectID IN (
          SELECT pkTestSubjectID
          FROM MM_Test_Subjects
          WHERE fkCSTStrandID IN (
                  SELECT number FROM itot(@strAcceptableStrands, N','))
            AND fkTestTypeID = 1)
    AND s.fkScoreTypeID = 3

  INNER JOIN StudentScores_Subject sPre
     ON sPre.fkStudentTestID = stPre.pkStudentTestID
    AND sPre.fkTest_SubjectID IN (
          SELECT pkTestSubjectID
          FROM MM_Test_Subjects
          WHERE fkCSTStrandID IN (
                  SELECT number FROM itot(@strAcceptableStrands, N','))
            AND fkTestTypeID = 1)
    AND sPre.fkScoreTypeID = 3

  INNER JOIN MM_Test_PL_SS_Ranges r
     ON r.fkTest_SubjectID = s.fkTest_SubjectID
    AND r.fkSchoolYearID = ti.fkSchoolYearID
    AND r.fkTestTypeID = ti.fkTestTypeID
    AND (r.fkGradeID = st.fkGradeID OR r.fkGradeID = 99)

  INNER JOIN MM_Test_PL_SS_Ranges rPre
     ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
    AND rPre.fkSchoolYearID = tiPre.fkSchoolYearID
    AND rPre.fkTestTypeID = tiPre.fkTestTypeID
    AND (rPre.fkGradeID = stPre.fkGradeID OR rPre.fkGradeID = 99)

  INNER JOIN StudentScores_Subject s2
     ON s2.fkStudentTestID = st.pkStudentTestID
    AND s2.fkTest_SubjectID = s.fkTest_SubjectID
    AND s2.fkScoreTypeID = 2

  INNER JOIN StudentScores_Subject sPre2
     ON sPre2.fkStudentTestID = stPre.pkStudentTestID
    AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
    AND sPre2.fkScoreTypeID = 2

  INNER JOIN Students
     ON Students.pkStudentID = st.fkStudentID

Body:
Take a look at your execution plan.  My guess is that doing the calculation in the join aka (TestInstancesPre.fkSchoolYearID + 1) is causing indexes not be used correctly.  An easy way to test this would be to change your join to:

TestInstances.fkSchoolYearID = TestInstancesPre.fkSchoolYearID

I have seen performance go way down when doing funky stuff in a join.  Things like:

ON t1.column1 = ISNULL(t2.myColumn, 1)

I believe this is because the query becomes non-sargable.  Take a look at this SO post for more details on that.